| Line 0
          
      
      
        Link Here | 
            
              |  |  | 1 | package Koha::FloatingMatrix; | 
            
              | 2 |  | 
            
              | 3 | # Copyright 2015 Vaara-kirjastot | 
            
              | 4 | # | 
            
              | 5 | # This file is part of Koha. | 
            
              | 6 | # | 
            
              | 7 | # Koha is free software; you can redistribute it and/or modify it under the | 
            
              | 8 | # terms of the GNU General Public License as published by the Free Software | 
            
              | 9 | # Foundation; either version 2 of the License, or (at your option) any later | 
            
              | 10 | # version. | 
            
              | 11 | # | 
            
              | 12 | # Koha is distributed in the hope that it will be useful, but WITHOUT ANY | 
            
              | 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | 
            
              | 14 | # A PARTICULAR PURPOSE.  See the GNU General Public License for more details. | 
            
              | 15 | # | 
            
              | 16 | # You should have received a copy of the GNU General Public License along | 
            
              | 17 | # with Koha; if not, write to the Free Software Foundation, Inc., | 
            
              | 18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 
            
              | 19 |  | 
            
              | 20 | =head1 FloatingMatrix | 
            
              | 21 |  | 
            
              | 22 | Koha::FloatingMatrix - Object to control accessing and modifying floating matrix rules. | 
            
              | 23 |  | 
            
              | 24 | =cut | 
            
              | 25 |  | 
            
              | 26 | use Modern::Perl; | 
            
              | 27 | use Carp qw(carp croak confess longmess); | 
            
              | 28 | use Scalar::Util qw(blessed refaddr); | 
            
              | 29 |  | 
            
              | 30 | use C4::Context qw(dbh); | 
            
              | 31 | use Koha::Caches; | 
            
              | 32 | use Koha::Database; | 
            
              | 33 |  | 
            
              | 34 | use Koha::FloatingMatrix::BranchRule; | 
            
              | 35 |  | 
            
              | 36 | use Koha::Exceptions::BadParameter; | 
            
              | 37 |  | 
            
              | 38 | my $cacheExpiryTime = 1200; | 
            
              | 39 |  | 
            
              | 40 | =head new | 
            
              | 41 |  | 
            
              | 42 |     my $fm = Koha::FloatingMatrix->new(); | 
            
              | 43 |  | 
            
              | 44 | Finds a FloatingMatrix from Koha::Caches or instantiates a new one. | 
            
              | 45 |  | 
            
              | 46 | =cut | 
            
              | 47 |  | 
            
              | 48 | sub new { | 
            
              | 49 |     my ($class) = @_; | 
            
              | 50 |  | 
            
              | 51 |     my $cache = Koha::Caches->get_instance(); | 
            
              | 52 |     my $fm = $cache->get_from_cache('floatingMatrix'); | 
            
              | 53 |     unless ($fm) { | 
            
              | 54 |         $fm = {}; | 
            
              | 55 |         bless $fm, $class; | 
            
              | 56 |         $fm->_getFloatingMatrix(); | 
            
              | 57 |         $fm->_createModificationBuffer(); | 
            
              | 58 |         $cache->set_in_cache('floatingMatrix', $fm, {expiry => $cacheExpiryTime}); | 
            
              | 59 |     } | 
            
              | 60 |     return $fm if blessed($fm) && $fm->isa('Koha::FloatingMatrix'); | 
            
              | 61 |     return undef; | 
            
              | 62 | } | 
            
              | 63 |  | 
            
              | 64 | sub _getFloatingMatrix { | 
            
              | 65 |     my ($fm) = @_; | 
            
              | 66 |  | 
            
              | 67 |     my $schema = Koha::Database->new()->schema(); | 
            
              | 68 |     my @rules = $schema->resultset('FloatingMatrix')->search({}); | 
            
              | 69 |  | 
            
              | 70 |     my %map; | 
            
              | 71 |     $fm->_setBranchRules( \%map ); | 
            
              | 72 |     foreach my $rule (@rules) { | 
            
              | 73 |         my $branchRule = Koha::FloatingMatrix::BranchRule->newFromDBIx($rule); | 
            
              | 74 |         $fm->_linkBranchRule($branchRule); | 
            
              | 75 |     } | 
            
              | 76 | } | 
            
              | 77 |  | 
            
              | 78 | =head GetFloatingTypes | 
            
              | 79 | Static Method | 
            
              | 80 |  | 
            
              | 81 |     my $floatingTypes = Koha::FloatingMatrix::GetFloatingTypes(); | 
            
              | 82 |  | 
            
              | 83 | @RETURNS Reference to ARRAY, of koha.floating_matrix.floating enumerations. | 
            
              | 84 |             These are all the available ways Items can float in Koha. | 
            
              | 85 | =cut | 
            
              | 86 |  | 
            
              | 87 | sub GetFloatingTypes { | 
            
              | 88 |     my $schema = Koha::Database->new()->schema(); | 
            
              | 89 |     my $source = $schema->source('FloatingMatrix'); | 
            
              | 90 |     my $info = $source->column_info('floating'); | 
            
              | 91 |     my $floatingTypeEnumerations =  $info->{extra}->{list}; | 
            
              | 92 |     return $floatingTypeEnumerations; | 
            
              | 93 | } | 
            
              | 94 |  | 
            
              | 95 | =head getFloatingTypes | 
            
              | 96 |     $fm->getFloatingTypes(); | 
            
              | 97 | See. GetFloatingTypes() | 
            
              | 98 | =cut | 
            
              | 99 | sub getFloatingTypes { | 
            
              | 100 |     my ($fm) = @_; | 
            
              | 101 |  | 
            
              | 102 |     return $fm->{floatingTypes} if $fm->{floatingTypes}; | 
            
              | 103 |  | 
            
              | 104 |     $fm->{floatingTypes} = Koha::FloatingMatrix::GetFloatingTypes(); | 
            
              | 105 |     return $fm->{floatingTypes}; | 
            
              | 106 | } | 
            
              | 107 |  | 
            
              | 108 | =head upsertBranchRule | 
            
              | 109 |  | 
            
              | 110 |     my ($branchRule, $error) = $fm->upsertBranchRule( $params ); | 
            
              | 111 |     if ($error) { | 
            
              | 112 |         #I must have given some bad object properties | 
            
              | 113 |     } | 
            
              | 114 |     else { | 
            
              | 115 |         $fm->store(); | 
            
              | 116 |     } | 
            
              | 117 |  | 
            
              | 118 | Adds or modifies an existing overduerule. Take note that this is only a local modification | 
            
              | 119 | for this instance of OverdueRulesMap-object. | 
            
              | 120 | If changes need to persists, call the $orm->store() method to save changes to DB. | 
            
              | 121 |  | 
            
              | 122 | @PARAM1, HASH, See Koha::Overdues::OverdueRule->new() for parameter descriptions. | 
            
              | 123 | @RETURN, Koha::Overdues::OverdueRule-object if success and | 
            
              | 124 |          String errorCode, if something bad hapened. | 
            
              | 125 |  | 
            
              | 126 | @THROWS Koha::Exceptions::BadParameter from Koha::FloatingMatrix::BranchRule->new(). | 
            
              | 127 | =cut | 
            
              | 128 |  | 
            
              | 129 | sub upsertBranchRule { | 
            
              | 130 |     my ($fm, $params) = @_; | 
            
              | 131 |  | 
            
              | 132 |     my $branchRule = Koha::FloatingMatrix::BranchRule->new($params); #While creating this object we sanitate the parameters. | 
            
              | 133 |  | 
            
              | 134 |     my $existingBranchRule = $fm->_findBranchRule($branchRule); | 
            
              | 135 |     my $operation; | 
            
              | 136 |     if ($existingBranchRule) { #We are modifying an existing rule | 
            
              | 137 |         #Should we somehow tell that we are updating an existing rule? | 
            
              | 138 |         $existingBranchRule->replace($branchRule); #Replace with the new sanitated values, we preserve the internal data structure position. | 
            
              | 139 |         #Replacing might be less costly than recursively unlinking a large internal mapping. | 
            
              | 140 |         $branchRule = $existingBranchRule; | 
            
              | 141 |         $operation = 'MOD'; | 
            
              | 142 |     } | 
            
              | 143 |     else { #Just adding more rules | 
            
              | 144 |         $fm->_linkBranchRule($branchRule); | 
            
              | 145 |         $operation = 'ADD'; | 
            
              | 146 |     } | 
            
              | 147 |  | 
            
              | 148 |     $fm->_pushToModificationBuffer([$branchRule, $operation]); | 
            
              | 149 |     return $branchRule; | 
            
              | 150 | } | 
            
              | 151 |  | 
            
              | 152 | =head getBranchRule | 
            
              | 153 |  | 
            
              | 154 |     my $branchRule = $fm->getBranchRule( $fromBranch, $toBranch ); | 
            
              | 155 |  | 
            
              | 156 | @PARAM1 String, koha.floating_matrix.from_branch, must give @PARAM2 as well | 
            
              | 157 | @PARAM2 String, koha.floating_matrix.to_branch, must give @PARAM1 as well | 
            
              | 158 | @RETURNS Koha::FloatingMatrix::BranchRule-object matching the params or undef. | 
            
              | 159 | =cut | 
            
              | 160 |  | 
            
              | 161 | sub getBranchRule { | 
            
              | 162 |     my ($fm, $fromBranch, $toBranch) = @_; | 
            
              | 163 |  | 
            
              | 164 |     my $branchRule = $fm->_findBranchRule(undef, $fromBranch, $toBranch); | 
            
              | 165 |  | 
            
              | 166 |     return $branchRule; | 
            
              | 167 | } | 
            
              | 168 |  | 
            
              | 169 | =head getBranchRules | 
            
              | 170 |  | 
            
              | 171 |     my $branchRules = $fm->getBranchRules(); | 
            
              | 172 |  | 
            
              | 173 | @RETURNS Reference to a HASH of Koha::FloatingMatrix::BranchRule-objects | 
            
              | 174 |          Hash keys are <fromBranch>-<toBranch>, eg. FFL-CPL | 
            
              | 175 | =cut | 
            
              | 176 |  | 
            
              | 177 | sub getBranchRules { | 
            
              | 178 |     my ($fm) = @_; | 
            
              | 179 |     return $fm->{branchRules}; | 
            
              | 180 | } | 
            
              | 181 |  | 
            
              | 182 | =head _setBranchRules | 
            
              | 183 | Needs to be called only from the _getFloatingMatrix() to bind the branchRules-map to this object. | 
            
              | 184 | @PARAM1, Reference to HASH. | 
            
              | 185 | =cut | 
            
              | 186 |  | 
            
              | 187 | sub _setBranchRules { | 
            
              | 188 |     my ($fm, $hash) = @_; | 
            
              | 189 |     $fm->{branchRules} = $hash; | 
            
              | 190 | } | 
            
              | 191 |  | 
            
              | 192 | sub checkFloating { | 
            
              | 193 |     my ($fm, $item, $checkinBranch, $transferTargetBranch) = @_; | 
            
              | 194 |     unless ($transferTargetBranch) { #If no transfer branch is given, then we try our best to figure it out. | 
            
              | 195 |         my $branchItemRule = C4::Circulation::GetBranchItemRule($item->{'homebranch'}, $item->{'itype'}); | 
            
              | 196 |         my $returnBranchRule = $branchItemRule->{'returnbranch'} || "homebranch"; | 
            
              | 197 |         # get the proper branch to which to return the item | 
            
              | 198 |         $transferTargetBranch = $item->{$returnBranchRule} || C4::Context->userenv->{'branch'}; | 
            
              | 199 |     } | 
            
              | 200 |  | 
            
              | 201 |     #If the check-in branch and transfer branch are the same, then no point in transferring. | 
            
              | 202 |     if ($checkinBranch eq $transferTargetBranch) { | 
            
              | 203 |         return undef; | 
            
              | 204 |     } | 
            
              | 205 |  | 
            
              | 206 |     my $branchRule = $fm->getBranchRule($checkinBranch, $transferTargetBranch); | 
            
              | 207 |     if ($branchRule) { | 
            
              | 208 |         my $floating = $branchRule->getFloating(); | 
            
              | 209 |         if ($floating eq 'ALWAYS') { | 
            
              | 210 |             return 'ALWAYS'; | 
            
              | 211 |         } | 
            
              | 212 |         elsif ($floating eq 'POSSIBLE') { | 
            
              | 213 |             return 'POSSIBLE'; | 
            
              | 214 |         } | 
            
              | 215 |         elsif ($floating eq 'CONDITIONAL') { | 
            
              | 216 |             if(_CheckConditionalFloat($item, $branchRule)) { | 
            
              | 217 |                 return 'ALWAYS'; | 
            
              | 218 |             } | 
            
              | 219 |         } | 
            
              | 220 |         else { | 
            
              | 221 |             warn "FloatingMatrix->checkFloating():> Bad floating type for route from '$checkinBranch' to '$transferTargetBranch'. Not floating.\n"; | 
            
              | 222 |         } | 
            
              | 223 |     } | 
            
              | 224 |     return undef; | 
            
              | 225 | } | 
            
              | 226 |  | 
            
              | 227 | =head _CheckConditionalFloat | 
            
              | 228 | Static method | 
            
              | 229 |  | 
            
              | 230 | @PARAM1, HASH of koha.items-row | 
            
              | 231 | @PARAM2, Koha::FloatingMatrix::BranchRule-object | 
            
              | 232 | @RETURNS 1 if floats, undef if not. | 
            
              | 233 | =cut | 
            
              | 234 |  | 
            
              | 235 | sub _CheckConditionalFloat { | 
            
              | 236 |     my ($item, $branchRule) = @_; | 
            
              | 237 |  | 
            
              | 238 |     my $conditionRules = $branchRule->getConditionRules(); | 
            
              | 239 |  | 
            
              | 240 |     my $evalCondition = ''; | 
            
              | 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);"); | 
            
              | 257 |     if ($@) { | 
            
              | 258 |         warn "Koha::FloatingMatrix::_CheckConditionalFloat():> Something bad hapened when trying to evaluate the dynamic conditional:\n$@\n"; | 
            
              | 259 |         return undef; | 
            
              | 260 |     } | 
            
              | 261 |     return $ok; | 
            
              | 262 | } | 
            
              | 263 |  | 
            
              | 264 | =head CheckFloating | 
            
              | 265 | Static Subroutine | 
            
              | 266 |  | 
            
              | 267 | A convenience Subroutine to checkFloating without intantiating a new Koha::FloatingMatrix-object | 
            
              | 268 | =cut | 
            
              | 269 |  | 
            
              | 270 | sub CheckFloating { | 
            
              | 271 |     my ($item, $checkinBranch, $transferTargetBranch) = @_; | 
            
              | 272 |     my $fm = Koha::FloatingMatrix->new(); | 
            
              | 273 |     return $fm->checkFloating($item, $checkinBranch, $transferTargetBranch); | 
            
              | 274 | } | 
            
              | 275 |  | 
            
              | 276 | =head _findBranchRule | 
            
              | 277 |  | 
            
              | 278 |     my $branchRule = $fm->_findBranchRule( undef, $fromBranch, $toBranch ); | 
            
              | 279 |     my $existingBranchRule = $fm->_findBranchRule( $branchRule ); | 
            
              | 280 |  | 
            
              | 281 | Finds a branch rule from the internal floating matrix map. | 
            
              | 282 |  | 
            
              | 283 | This abstracts the retrieval of branch rules, so we can later change the internal mapping. | 
            
              | 284 | @PARAM1, Koha::FloatingMatrix::BranchRule-object, to see if a BranchRule with same targeting rules is present. | 
            
              | 285 |          or undef, if you are only interested in retrieving. | 
            
              | 286 | @PARAM2-3, MANDATORY if no @PARAM1 given, Targeting rules to find a BranchRule. | 
            
              | 287 | @RETURNS Koha::FloatingMatrix::BranchRule-object, of the object occupying the given position. | 
            
              | 288 |          or undef if nothing is found. | 
            
              | 289 | =cut | 
            
              | 290 |  | 
            
              | 291 | sub _findBranchRule { | 
            
              | 292 |     my ($fm, $branchRule, $fromBranch, $toBranch) = @_; | 
            
              | 293 |     if (blessed($branchRule) && $branchRule->isa('Koha::FloatingMatrix::BranchRule')) { | 
            
              | 294 |         $fromBranch = $branchRule->getFromBranch(); | 
            
              | 295 |         $toBranch   = $branchRule->getToBranch(); | 
            
              | 296 |     } | 
            
              | 297 |  | 
            
              | 298 |     my $existingBranchRule = $fm->getBranchRules()->{  $fromBranch  }->{  $toBranch  }; | 
            
              | 299 |     return $existingBranchRule; | 
            
              | 300 | } | 
            
              | 301 |  | 
            
              | 302 | =head _linkBranchRule | 
            
              | 303 |  | 
            
              | 304 |     my $existingBranchRule = $fm->_linkBranchRule( $branchRule ); | 
            
              | 305 |  | 
            
              | 306 | Links the new branchrule to the internal floating matrix map, overwriting a possible existing | 
            
              | 307 | reference to a BranchRule, and losing that into the binary limbo. | 
            
              | 308 |  | 
            
              | 309 | This abstracts the retrieval of floating matrix routes, so we can later change the internal mapping. | 
            
              | 310 | @PARAM1, Koha::FloatingMatrix::BranchRule-object, to link to the internal mapping | 
            
              | 311 | =cut | 
            
              | 312 |  | 
            
              | 313 | sub _linkBranchRule { | 
            
              | 314 |     my ($fm, $branchRule) = @_; | 
            
              | 315 |  | 
            
              | 316 |     $fm->{branchRules}->{  $branchRule->getFromBranch()  }->{  $branchRule->getToBranch()  } = $branchRule; | 
            
              | 317 | } | 
            
              | 318 |  | 
            
              | 319 | =head _unlinkBranchRule | 
            
              | 320 |  | 
            
              | 321 |     my $existingBranchRule = $fm->_unlinkBranchRule( $branchRule ); | 
            
              | 322 |  | 
            
              | 323 | Unlinks the branchRule from the internal floating matrix map and releasing it into the binary limbo. | 
            
              | 324 |  | 
            
              | 325 | This abstracts the internal mapping of branch rules, so we can later change it. | 
            
              | 326 | @PARAM1, Koha::FloatingMatrix::BranchRule-object | 
            
              | 327 |  | 
            
              | 328 | =cut | 
            
              | 329 |  | 
            
              | 330 | sub _unlinkBranchRule { | 
            
              | 331 |     my ($fm, $branchRule) = @_; | 
            
              | 332 |  | 
            
              | 333 |     #Delete the BranchRule | 
            
              | 334 |     my $branchRules = $fm->getBranchRules(); | 
            
              | 335 |     my $fromBranch = $branchRule->getFromBranch(); | 
            
              | 336 |     my $toBranch = $branchRule->getToBranch(); | 
            
              | 337 |  | 
            
              | 338 |     eval{ delete( $branchRules->{  $fromBranch  }->{  $toBranch  } ); }; | 
            
              | 339 |     if ($@) { | 
            
              | 340 |         carp "Unlinking BranchRule failed because of '".$@."'. Something wrong with this BranchRule\n".$branchRule->toString()."\n"; | 
            
              | 341 |         return $@; | 
            
              | 342 |     } | 
            
              | 343 |  | 
            
              | 344 |     unless (scalar(%{$branchRules->{  $fromBranch  }})) { | 
            
              | 345 |         #Delete the branchLevel | 
            
              | 346 |         delete( $branchRules->{  $fromBranch  } ); | 
            
              | 347 |     } | 
            
              | 348 | } | 
            
              | 349 |  | 
            
              | 350 | =head deleteBranchRule | 
            
              | 351 |  | 
            
              | 352 |     $fm->deleteBranchRule($branchRule); | 
            
              | 353 |     $fm->deleteBranchRule($fromBranch, $toBranch); | 
            
              | 354 |  | 
            
              | 355 | Deletes the BranchRule from the internal mapping, but not from the DB. | 
            
              | 356 | Call $fm->store() to persist the removal. | 
            
              | 357 |  | 
            
              | 358 | The given $branchRule must be the same object gained using $fm->getBranchRule(), | 
            
              | 359 | or you are misusing the FloatingMatrix-object and bad things might happen. | 
            
              | 360 |  | 
            
              | 361 | @PARAM1, Koha::FloatingMatrix::BranchRule-object to delete from DB. | 
            
              | 362 | or | 
            
              | 363 | @PARAM1 {String, koha.floating_matrix.from_branch} | 
            
              | 364 | @PARAM1 {String, koha.floating_matrix.to_branch} | 
            
              | 365 |  | 
            
              | 366 | @THROWS Koha::Exceptions::BadParameter if no branchRule, with the given parameters, is found, | 
            
              | 367 |                 or the given BranchRule doesn't match the one in the internal mapping. | 
            
              | 368 | =cut | 
            
              | 369 |  | 
            
              | 370 | sub deleteBranchRule { | 
            
              | 371 |     my ($fm, $fromBranch, $toBranch) = @_; | 
            
              | 372 |     my ($branchRule, $branchRuleLocal); | 
            
              | 373 |     #Process given parameters, see if we use parameter group1 (BranchRule-object) or group2 (branchcodes)? | 
            
              | 374 |     if (blessed $fromBranch && $fromBranch->isa('Koha::FloatingMatrix::BranchRule')) { | 
            
              | 375 |         $branchRule = $fromBranch; | 
            
              | 376 |         $fromBranch = $branchRule->getFromBranch(); | 
            
              | 377 |         $toBranch = $branchRule->getToBranch(); | 
            
              | 378 |     } | 
            
              | 379 |  | 
            
              | 380 |     $branchRuleLocal = $fm->getBranchRule($fromBranch, $toBranch); | 
            
              | 381 |     Koha::Exceptions::BadParameter->throw(error => "Koha::FloatingMatrix->deleteBranchRule($fromBranch, $toBranch):> No BranchRule exists for the given fromBranch '$fromBranch' and toBranch '$toBranch'") | 
            
              | 382 |                 unless $branchRuleLocal; | 
            
              | 383 |  | 
            
              | 384 |     $fm->_unlinkBranchRule(  $branchRuleLocal  ); | 
            
              | 385 |     $fm->_pushToModificationBuffer([$branchRuleLocal, 'DEL']); | 
            
              | 386 | } | 
            
              | 387 |  | 
            
              | 388 | =head $fm->deleteAllFloatingMatrixRules() | 
            
              | 389 |  | 
            
              | 390 | Deletes all Floating matrix rules in the DB, shows no pity. | 
            
              | 391 | Invalidates $fm in the Koha::Caches | 
            
              | 392 | =cut | 
            
              | 393 |  | 
            
              | 394 | sub deleteAllFloatingMatrixRules { | 
            
              | 395 |     my ($fm) = @_; | 
            
              | 396 |     my $schema = Koha::Database->new()->schema(); | 
            
              | 397 |     $schema->resultset('FloatingMatrix')->search({})->delete_all; | 
            
              | 398 |     $fm = undef; | 
            
              | 399 |  | 
            
              | 400 |     my $cache = Koha::Caches->get_instance(); | 
            
              | 401 |     $cache->clear_from_cache('floatingMatrix'); | 
            
              | 402 | } | 
            
              | 403 |  | 
            
              | 404 | =head store | 
            
              | 405 |  | 
            
              | 406 |     $fm->store(); | 
            
              | 407 |  | 
            
              | 408 | Saves all pending transactions to DB, by calling the Koha::FloatingMatrix::BranchRule->store() || delete(); | 
            
              | 409 |  | 
            
              | 410 | =cut | 
            
              | 411 |  | 
            
              | 412 | sub store { | 
            
              | 413 |     my $fm = shift; | 
            
              | 414 |     my $schema = Koha::Database->new()->schema(); | 
            
              | 415 |  | 
            
              | 416 |     my $pendingModifications = $fm->_consumeModificationBuffer(); | 
            
              | 417 |     foreach my $modRequest (@$pendingModifications) { | 
            
              | 418 |         my $branchRule = $modRequest->[0]; | 
            
              | 419 |         my $operation = $modRequest->[1]; | 
            
              | 420 |         if ($operation eq 'MOD' || $operation eq 'ADD') { | 
            
              | 421 |             $branchRule->store(); | 
            
              | 422 |         } | 
            
              | 423 |         elsif ($operation eq 'DEL') { | 
            
              | 424 |             $branchRule->delete(); | 
            
              | 425 |         } | 
            
              | 426 |         else { | 
            
              | 427 |             carp "Unsupported database access operation '$operation'!"; | 
            
              | 428 |         } | 
            
              | 429 |     } | 
            
              | 430 |  | 
            
              | 431 |     my $cache = Koha::Caches->get_instance(); | 
            
              | 432 |     $cache->set_in_cache('floatingMatrix', $fm, {expiry => $cacheExpiryTime}); | 
            
              | 433 | } | 
            
              | 434 |  | 
            
              | 435 | =head _pushToModificationBuffer | 
            
              | 436 |  | 
            
              | 437 |     $fm->_pushToModificationBuffer([$branchRule, $operation]); | 
            
              | 438 |  | 
            
              | 439 | To be able to more effectively service DB write operations, especially when using | 
            
              | 440 | FloatingMatrix with an REST(ful?) API giving lots of write operations, it is useful | 
            
              | 441 | to be able to know which BranchRules need changing and which do not. | 
            
              | 442 | Thus we don't need to either | 
            
              | 443 | DELETE all BranchRules from DB and re-add them (what if the rewrite request dies?) | 
            
              | 444 |   or | 
            
              | 445 | check each rule for possible changes. | 
            
              | 446 |  | 
            
              | 447 | The modification buffer tells what information needs changing. | 
            
              | 448 |  | 
            
              | 449 | To write the changes to DB, use $fm->store(). | 
            
              | 450 |  | 
            
              | 451 | @PARAM1, Tuple (Two-index ARRAY reference). [0] = $branchRule (see. upsertBranchRule()) | 
            
              | 452 |                                             [1] = The operation, either 'ADD', 'MOD' or 'DEL' | 
            
              | 453 | @RETURN, always nothing. | 
            
              | 454 |  | 
            
              | 455 | =cut | 
            
              | 456 |  | 
            
              | 457 | sub _pushToModificationBuffer { | 
            
              | 458 |     my ($fm, $tuple) = @_; | 
            
              | 459 |     push @{$fm->{modBuffer}}, $tuple; | 
            
              | 460 |     return undef; | 
            
              | 461 | } | 
            
              | 462 | =head _consumeModificationBuffer | 
            
              | 463 | Detaches the modification buffer from the FloatingMatrix (parent) and returns it. | 
            
              | 464 | Fm now has an empty modification buffer ready for new modifications. | 
            
              | 465 | =cut | 
            
              | 466 |  | 
            
              | 467 | sub _consumeModificationBuffer { | 
            
              | 468 |     my ($fm) = @_; | 
            
              | 469 |     my $modBuffer = $fm->{modBuffer}; | 
            
              | 470 |     $fm->{modBuffer} = []; | 
            
              | 471 |     return $modBuffer; | 
            
              | 472 | } | 
            
              | 473 | sub _createModificationBuffer { | 
            
              | 474 |     my ($fm) = @_; | 
            
              | 475 |     $fm->{modBuffer} = []; | 
            
              | 476 |     return undef; | 
            
              | 477 | } | 
            
              | 478 |  | 
            
              | 479 | 1; #Satisfy the compiler |