Bug 14544: Koha::Virtualshelfcontent[s]
[srvgit] / Koha / Calendar.pm
index 90069b6..a0b642b 100644 (file)
@@ -7,8 +7,8 @@ use DateTime;
 use DateTime::Set;
 use DateTime::Duration;
 use C4::Context;
 use DateTime::Set;
 use DateTime::Duration;
 use C4::Context;
+use Koha::Cache;
 use Carp;
 use Carp;
-use Readonly;
 
 sub new {
     my ( $classname, %options ) = @_;
 
 sub new {
     my ( $classname, %options ) = @_;
@@ -18,10 +18,6 @@ sub new {
         my $o = lc $o_name;
         $self->{$o} = $options{$o_name};
     }
         my $o = lc $o_name;
         $self->{$o} = $options{$o_name};
     }
-    if ( exists $options{TEST_MODE} ) {
-        $self->_mockinit();
-        return $self;
-    }
     if ( !defined $self->{branchcode} ) {
         croak 'No branchcode argument passed to Koha::Calendar->new';
     }
     if ( !defined $self->{branchcode} ) {
         croak 'No branchcode argument passed to Koha::Calendar->new';
     }
@@ -33,28 +29,52 @@ sub _init {
     my $self       = shift;
     my $branch     = $self->{branchcode};
     my $dbh        = C4::Context->dbh();
     my $self       = shift;
     my $branch     = $self->{branchcode};
     my $dbh        = C4::Context->dbh();
-    my $repeat_sth = $dbh->prepare(
-'SELECT * from repeatable_holidays WHERE branchcode = ? AND ISNULL(weekday) = ?'
+    my $weekly_closed_days_sth = $dbh->prepare(
+'SELECT weekday FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NOT NULL'
     );
     );
-    $repeat_sth->execute( $branch, 0 );
+    $weekly_closed_days_sth->execute( $branch );
     $self->{weekly_closed_days} = [ 0, 0, 0, 0, 0, 0, 0 ];
     $self->{weekly_closed_days} = [ 0, 0, 0, 0, 0, 0, 0 ];
-    Readonly::Scalar my $sunday => 7;
-    while ( my $tuple = $repeat_sth->fetchrow_hashref ) {
+    while ( my $tuple = $weekly_closed_days_sth->fetchrow_hashref ) {
         $self->{weekly_closed_days}->[ $tuple->{weekday} ] = 1;
     }
         $self->{weekly_closed_days}->[ $tuple->{weekday} ] = 1;
     }
-    $repeat_sth->execute( $branch, 1 );
+    my $day_month_closed_days_sth = $dbh->prepare(
+'SELECT day, month FROM repeatable_holidays WHERE branchcode = ? AND weekday IS NULL'
+    );
+    $day_month_closed_days_sth->execute( $branch );
     $self->{day_month_closed_days} = {};
     $self->{day_month_closed_days} = {};
-    while ( my $tuple = $repeat_sth->fetchrow_hashref ) {
+    while ( my $tuple = $day_month_closed_days_sth->fetchrow_hashref ) {
         $self->{day_month_closed_days}->{ $tuple->{month} }->{ $tuple->{day} } =
           1;
     }
 
         $self->{day_month_closed_days}->{ $tuple->{month} }->{ $tuple->{day} } =
           1;
     }
 
-    my $special = $dbh->prepare(
-'SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = ?'
+    $self->{days_mode}       = C4::Context->preference('useDaysMode');
+    $self->{test}            = 0;
+    return;
+}
+
+
+# FIXME: use of package-level variables for caching the holiday
+# lists breaks persistance engines.  As of 2013-12-10, the RM
+# is allowing this with the expectation that prior to release of
+# 3.16, bug 8089 will be fixed and we can switch the caching over
+# to Koha::Cache.
+
+our $exception_holidays;
+
+sub exception_holidays {
+    my ( $self ) = @_;
+    my $dbh = C4::Context->dbh;
+    my $branch = $self->{branchcode};
+    if ( $exception_holidays ) {
+        $self->{exception_holidays} = $exception_holidays;
+        return $exception_holidays;
+    }
+    my $exception_holidays_sth = $dbh->prepare(
+'SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 1'
     );
     );
-    $special->execute( $branch, 1 );
+    $exception_holidays_sth->execute( $branch );
     my $dates = [];
     my $dates = [];
-    while ( my ( $day, $month, $year ) = $special->fetchrow ) {
+    while ( my ( $day, $month, $year ) = $exception_holidays_sth->fetchrow ) {
         push @{$dates},
           DateTime->new(
             day       => $day,
         push @{$dates},
           DateTime->new(
             day       => $day,
@@ -65,22 +85,61 @@ sub _init {
     }
     $self->{exception_holidays} =
       DateTime::Set->from_datetimes( dates => $dates );
     }
     $self->{exception_holidays} =
       DateTime::Set->from_datetimes( dates => $dates );
+    $exception_holidays = $self->{exception_holidays};
+    return $exception_holidays;
+}
 
 
-    $special->execute( $branch, 0 );
-    $dates = [];
-    while ( my ( $day, $month, $year ) = $special->fetchrow ) {
-        push @{$dates},
-          DateTime->new(
-            day       => $day,
-            month     => $month,
-            year      => $year,
-            time_zone => C4::Context->tz()
-          )->truncate( to => 'day' );
+sub single_holidays {
+    my ( $self, $date ) = @_;
+    my $branchcode = $self->{branchcode};
+    my $cache           = Koha::Cache->get_instance();
+    my $single_holidays = $cache->get_from_cache('single_holidays');
+
+    # $single_holidays looks like:
+    # {
+    #   CPL =>  [
+    #        [0] 20131122,
+    #         ...
+    #    ],
+    #   ...
+    # }
+
+    unless ($single_holidays) {
+        my $dbh = C4::Context->dbh;
+        $single_holidays = {};
+
+        # push holidays for each branch
+        my $branches_sth =
+          $dbh->prepare('SELECT distinct(branchcode) FROM special_holidays');
+        $branches_sth->execute();
+        while ( my $br = $branches_sth->fetchrow ) {
+            my $single_holidays_sth = $dbh->prepare(
+'SELECT day, month, year FROM special_holidays WHERE branchcode = ? AND isexception = 0'
+            );
+            $single_holidays_sth->execute($branchcode);
+
+            my @ymd_arr;
+            while ( my ( $day, $month, $year ) =
+                $single_holidays_sth->fetchrow )
+            {
+                my $dt = DateTime->new(
+                    day       => $day,
+                    month     => $month,
+                    year      => $year,
+                    time_zone => C4::Context->tz()
+                )->truncate( to => 'day' );
+                push @ymd_arr, $dt->ymd('');
+            }
+            $single_holidays->{$br} = \@ymd_arr;
+        }    # br
+        $cache->set_in_cache( 'single_holidays', $single_holidays,
+            76800 )    #24 hrs ;
     }
     }
-    $self->{single_holidays} = DateTime::Set->from_datetimes( dates => $dates );
-    $self->{days_mode}       = C4::Context->preference('useDaysMode');
-    $self->{test}            = 0;
-    return;
+    my $holidays  = ( $single_holidays->{$branchcode} );
+    for my $hols  (@$holidays ) {
+            return 1 if ( $date == $hols )   #match ymds;
+    }
+    return 0;
 }
 
 sub addDate {
 }
 
 sub addDate {
@@ -96,7 +155,7 @@ sub addDate {
 
     if ( $unit eq 'hours' ) {
         # Fixed for legacy support. Should be set as a branch parameter
 
     if ( $unit eq 'hours' ) {
         # Fixed for legacy support. Should be set as a branch parameter
-        Readonly::Scalar my $return_by_hour => 10;
+        my $return_by_hour = 10;
 
         $dt = $self->addHours($startdate, $add_duration, $return_by_hour);
     } else {
 
         $dt = $self->addHours($startdate, $add_duration, $return_by_hour);
     } else {
@@ -136,6 +195,8 @@ sub addDays {
     my ( $self, $startdate, $days_duration ) = @_;
     my $base_date = $startdate->clone();
 
     my ( $self, $startdate, $days_duration ) = @_;
     my $base_date = $startdate->clone();
 
+    $self->{days_mode} ||= q{};
+
     if ( $self->{days_mode} eq 'Calendar' ) {
         # use the calendar to skip all days the library is closed
         # when adding
     if ( $self->{days_mode} eq 'Calendar' ) {
         # use the calendar to skip all days the library is closed
         # when adding
@@ -162,6 +223,7 @@ sub addDays {
             # Datedue, then use the calendar to push
             # the date to the next open day if holiday
             if ( $self->is_holiday($base_date) ) {
             # Datedue, then use the calendar to push
             # the date to the next open day if holiday
             if ( $self->is_holiday($base_date) ) {
+
                 if ( $days_duration->is_negative() ) {
                     $base_date = $self->prev_open_day($base_date);
                 } else {
                 if ( $days_duration->is_negative() ) {
                     $base_date = $self->prev_open_day($base_date);
                 } else {
@@ -176,20 +238,23 @@ sub addDays {
 
 sub is_holiday {
     my ( $self, $dt ) = @_;
 
 sub is_holiday {
     my ( $self, $dt ) = @_;
+
     my $localdt = $dt->clone();
     my $day   = $localdt->day;
     my $month = $localdt->month;
 
     $localdt->truncate( to => 'day' );
 
     my $localdt = $dt->clone();
     my $day   = $localdt->day;
     my $month = $localdt->month;
 
     $localdt->truncate( to => 'day' );
 
-    if ( $self->{exception_holidays}->contains($localdt) ) {
+
+    if ( $self->exception_holidays->contains($localdt) ) {
         # exceptions are not holidays
         return 0;
     }
 
     my $dow = $localdt->day_of_week;
     # Representation fix
         # exceptions are not holidays
         return 0;
     }
 
     my $dow = $localdt->day_of_week;
     # Representation fix
-    # TODO: Shouldn't we shift the rest of the $dow also?
+    # DateTime object dow (1-7) where Monday is 1
+    # Arrays are 0-based where 0 = Sunday, not 7.
     if ( $dow == 7 ) {
         $dow = 0;
     }
     if ( $dow == 7 ) {
         $dow = 0;
     }
@@ -202,7 +267,8 @@ sub is_holiday {
         return 1;
     }
 
         return 1;
     }
 
-    if ( $self->{single_holidays}->contains($localdt) ) {
+    my $ymd   = $localdt->ymd('')  ;
+    if ($self->single_holidays(  $ymd  ) == 1 ) {
         return 1;
     }
 
         return 1;
     }
 
@@ -241,6 +307,13 @@ sub days_between {
     my $start_dt = shift;
     my $end_dt   = shift;
 
     my $start_dt = shift;
     my $end_dt   = shift;
 
+    if ( $start_dt->compare($end_dt) > 0 ) {
+        # swap dates
+        my $int_dt = $end_dt;
+        $end_dt = $start_dt;
+        $start_dt = $int_dt;
+    }
+
 
     # start and end should not be closed days
     my $days = $start_dt->delta_days($end_dt)->delta_days;
 
     # start and end should not be closed days
     my $days = $start_dt->delta_days($end_dt)->delta_days;
@@ -284,31 +357,6 @@ sub hours_between {
 
 }
 
 
 }
 
-sub _mockinit {
-    my $self = shift;
-    $self->{weekly_closed_days} = [ 1, 0, 0, 0, 0, 0, 0 ];    # Sunday only
-    $self->{day_month_closed_days} = { 6 => { 16 => 1, } };
-    my $dates = [];
-    $self->{exception_holidays} =
-      DateTime::Set->from_datetimes( dates => $dates );
-    my $special = DateTime->new(
-        year      => 2011,
-        month     => 6,
-        day       => 1,
-        time_zone => 'Europe/London',
-    );
-    push @{$dates}, $special;
-    $self->{single_holidays} = DateTime::Set->from_datetimes( dates => $dates );
-
-    # if not defined, days_mode defaults to 'Calendar'
-    if ( !defined($self->{days_mode}) ) {
-        $self->{days_mode} = 'Calendar';
-    }
-
-    $self->{test} = 1;
-    return;
-}
-
 sub set_daysmode {
     my ( $self, $mode ) = @_;
 
 sub set_daysmode {
     my ( $self, $mode ) = @_;
 
@@ -326,17 +374,6 @@ sub clear_weekly_closed_days {
     return;
 }
 
     return;
 }
 
-sub add_holiday {
-    my $self = shift;
-    my $new_dt = shift;
-    my @dt = $self->{single_holidays}->as_list;
-    push @dt, $new_dt;
-    $self->{single_holidays} =
-      DateTime::Set->from_datetimes( dates => \@dt );
-
-    return;
-}
-
 1;
 __END__
 
 1;
 __END__
 
@@ -413,6 +450,13 @@ Currently unit is only used to invoke Staffs return Monday at 10 am rule this
 parameter will be removed when issuingrules properly cope with that
 
 
 parameter will be removed when issuingrules properly cope with that
 
 
+=head2 single_holidays
+
+my $rc = $self->single_holidays(  $ymd  );
+
+Passed a $date in Ymd (yyyymmdd) format -  returns 1 if date is a single_holiday, or 0 if not.
+
+
 =head2 is_holiday
 
 $yesno = $calendar->is_holiday($dt);
 =head2 is_holiday
 
 $yesno = $calendar->is_holiday($dt);