package calendar; use strict; use warnings; no warnings 'redefine'; use Data::Dumper; use Date::Calc(); use template(); use events(); our @EXPORT_OK = qw(init get_cached_or_render get render get_calendar_weeks configure_cache); sub init() { } sub get_cached_or_render($$$) { # my $output = $_[0] my $config = $_[1]; my $request = $_[2]; my $parms = $request->{params}->{checked}; my $calendar = calendar::get( $config, $request ); calendar::render( $_[0], $config, $request, $calendar ); } sub get($$) { my ($config, $request) = @_; my $params = $request->{params}->{checked}; my $language = $config->{date}->{language} || 'en'; my $date = $params->{date} || ''; my $template = $params->{template} || ''; my $from_time = $params->{from_time} || ''; my $till_time = $params->{till_time} || ''; my @today = localtime( time() ); my $today = sprintf( '%04d-%02d-%02d', 1900 + $today[5], $today[4] + 1, $today[3] ); my $weekday_names = time::getWeekdayNames($language); my $weekday_short_names = time::getWeekdayNamesShort($language); my $week_label = {}; my $c = 0; for my $weekday (@$weekday_short_names) { $week_label->{$weekday} = $weekday_names->[$c] || ''; $c++; } $template =~ s/\'//gi; $from_time =~ s/\'//gi; $till_time =~ s/\'//gi; #put "clear all" filter into final results my $day_result = {}; my $clear_filter = $day_result; #put "week day" filter into final results my $days = []; $c = 0; for my $weekday (@$weekday_short_names) { my $day_result = { label => $week_label->{$weekday}, weekday => $c + 1, weekday_parameter => 'weekday=' . $c, weekday_short_name => $weekday_short_names->[$c] || '', weekday_name => $weekday_names->[$c] || '', description => qq{alle $week_label->{$weekday}-Termine anzeigen}, }; push @$days, $day_result; $c++; } #weeks and days array my $weekAndDayResults = []; #weekday array my $weekdayResults = $days; #week array my $weekResults = []; #info hash by timedate my $dateInfo = {}; #generate content for each day in a week in a month in a year #get today my $start_date = ''; my $end_date = ''; if ( $date =~ /(\d{4})\-(\d{2})/ ) { my $year = $1; my $month = $2; $start_date = "$year-$month-01"; $end_date = "$year-$month-" . Date::Calc::Days_in_Month( $year, $month ); } else { $start_date = $params->{start_date}; $end_date = $params->{end_date}; } my $previous_month = $start_date; if ( $previous_month =~ /(\d{4})\-(\d{2})/ ) { my $year = $1; my $month = $2 - 1; $month = '0' . $month if ( length($month) < 2 ); if ( $month lt '01' ) { $year -= 1; $month = '12'; } $previous_month = "$year-$month-01"; $previous_month = $params->{start_date} if ( $previous_month lt $params->{start_date} ); } my $next_month = $end_date; if ( $next_month =~ /(\d{4})\-(\d{2})/ ) { my $year = $1; my $month = $2 + 1; $month = '0' . $month if ( length($month) < 2 ); if ( $month gt '12' ) { $year += 1; $month = '01'; } $next_month = "$year-$month-01"; $next_month = $params->{end_date} if ( $next_month gt $params->{end_date} ); } my $start_year = undef; my $start_month = undef; if ( $start_date =~ /(\d{4})\-(\d{2})/ ) { $start_year = $1; $start_month = $2; } my $monthNames = time::getMonthNamesShort($language); my $start_month_name = $monthNames->[ $start_month - 1 ]; if ( $params->{month_only} eq '1' ) { return { next_month => $next_month, previous_month => $previous_month, start_year => $start_year, start_month => $start_month, start_month_name => $start_month_name }; } my $years = calendar::get_calendar_weeks( $config, $start_date, $end_date ); my $dbh = db::connect( $config, $request ); my $used_days = events::get_by_date_range( $dbh, $config, $start_date, $end_date, { exclude_projects => 1, exclude_locations => 1, } ); my $used_day = { map { $_->{start_date} => 1 } @$used_days }; for my $year ( sort { $a <=> $b } keys %$years ) { my $months = $years->{$year}; for my $month ( sort { $a <=> $b } keys %$months ) { my $weeks = $months->{$month}; my $weekCounter = 1; for my $week (@$weeks) { my $dayResults = []; my $week_end = undef; my $week_start = undef; my $week_of_year = undef; my $woy_year = undef; for my $date (@$week) { my ( $year, $month, $day ) = split( /\-/, $date, 3 ); my $weekday = 0; my $day_result = undef; ( $week_of_year, $woy_year ) = Date::Calc::Week_of_Year( $year, $month, $day ) unless defined $week_of_year; $day_result = { date => $date, date_parameter => 'date=' . $date, day => $day, year => $year, month => $month, }; $day_result->{time} = $from_time if defined $from_time; $day_result->{class} .= ' calcms_today' if $date eq $today; $day_result->{class} .= ' selected' if defined $used_day->{$date}; $day_result->{class} .= " week_$weekCounter"; $day_result->{class} .= " other_month" if ( $weekCounter < 2 ) && ( $day gt "15" ); $day_result->{class} .= " other_month" if ( $weekCounter > 3 ) && ( $day lt "15" ); $day_result->{class} =~ s/^\s+//g; $week_start = $day unless defined $week_start; $week_end = $day; $day_result->{weekday_name} = $weekday_names->[$weekday]; $day_result->{weekday_short_name} = $weekday_short_names->[$weekday]; $day_result->{weekday} = $weekday + 1; $dateInfo->{ $day_result->{date} } = $day_result->{weekday} if defined $day_result->{date}; push @$dayResults, $day_result; $weekday++; } #end for days #week filter my $start_date = $week->[0]; my $end_date = $week->[-1]; my $week_result = { from_date => $start_date, till_date => $end_date, week_start => $week_start, week_end => $week_end, week_month => sprintf( "%2d", $month ), week_year => $year, week_of_year => $week_of_year, }; $week_result->{class} .= ' selected' if ( ( defined $params->{from_date} ) && ( $start_date eq $params->{from_date} ) ) || ( ( defined $params->{till_date} ) && ( $end_date eq $params->{till_date} ) ); $week_result->{class} .= " week_$weekCounter"; $week_result->{class} =~ s/^\s+//g; push @$weekResults, $week_result; push @$weekAndDayResults, { days => $dayResults, week => [$week_result] }; $weekCounter++; } #end week } #end month } #end year for my $weekday (@$weekdayResults) { $weekday->{start_date} = $start_date; $weekday->{end_date} = $end_date; } return { week_and_days => $weekAndDayResults, weekdays => $weekdayResults, weeks => $weekResults, days => $dateInfo, next_month => $next_month, previous_month => $previous_month, start_date => $start_date, end_date => $end_date, start_month_name => $start_month_name, start_month => $start_month, start_year => $start_year, base_url => $config->{locations}->{base_url}, widget_render_url=> $config->{locations}->{widget_render_url}, controllers => $config->{controllers}, }; } sub render($$$$) { # my $out = $_[0]; my $config = $_[1]; my $request = $_[2]; my $calendar = $_[3]; my $parms = $request->{params}->{checked}; my $template_parameters = $calendar; $template_parameters->{base_url} = $config->{locations}->{base_url}; $template_parameters->{widget_render_url}= $config->{locations}->{widget_render_url}; template::process( $config, $_[0], $parms->{template}, $template_parameters ); } sub get_calendar_weeks($$$) { my ($config, $start, $end) = @_; $start = time::date_to_array($start); $end = time::date_to_array($end); my $start_year = int( $start->[0] ); my $end_year = int( $end->[0] ); my $start_month = int( $start->[1] ); my $end_month = int( $end->[1] ); my $years = {}; for my $year ( $start_year .. $end_year ) { my $months = {}; for my $month ( $start_month .. $end_month ) { #get week arrays of days of the month my $weeks = getWeeksOfMonth( $year, $month ); $months->{$month} = $weeks; } $years->{$year} = $months; } return $years; } sub getWeeksOfMonth($$) { my ($thisYear, $thisMonth) = @_; my $thisDay = 1; # get weekday of 1st of month my $thisMonthWeekday = Date::Calc::Day_of_Week( $thisYear, $thisMonth, 1 ); # get next month date my ( $nextYear, $nextMonth, $nextDay ) = Date::Calc::Add_Delta_YM( $thisYear, $thisMonth, $thisDay, 0, 1 ); # get weekday of 1st of next month my $nextMonthWeekday = Date::Calc::Day_of_Week( $nextYear, $nextMonth, $nextDay ); my ( $lastYear, $lastMonth, $lastDayOfMonth ) = Date::Calc::Add_Delta_Days( $nextYear, $nextMonth, $nextDay, -1 ); # get date of 1st of row my ( $week, $year ) = Date::Calc::Week_of_Year( $thisYear, $thisMonth, $thisDay ); ( $year, my $month, my $day ) = Date::Calc::Monday_of_Week( $week, $year ); my @weeks = (); my $weekday = 1; { # first week my @days = (); for $weekday ( 0 .. $thisMonthWeekday - 2 ) { push @days, sprintf( "%04d-%02d-%02d", $year, $month, $day ); $day++; } # set current month $month = $thisMonth; $year = $thisYear; $day = 1; for $weekday ( $thisMonthWeekday .. 7 ) { push @days, sprintf( "%04d-%02d-%02d", $year, $month, $day ); $day++; } # next week push @weeks, \@days; } # weeks until end of month while ( scalar(@weeks) < 6 ) { my @days = (); $weekday = 1; while ( $weekday <= 7 ) { push @days, sprintf( "%04d-%02d-%02d", $year, $month, $day ); $day++; $weekday++; last if $day > $lastDayOfMonth; } if ( $day > $lastDayOfMonth ) { # set next month $month = $nextMonth; $year = $nextYear; $day = 1; if ( $nextMonthWeekday != 1 ) { # finish end week if ( $weekday <= 7 ) { while ( $weekday <= 7 ) { push @days, sprintf( "%04d-%02d-%02d", $year, $month, $day ); $day++; $weekday++; } } } push @weeks, \@days; last; } push @weeks, \@days if $weeks[-1]->[-1] ne $days[-1]; } #coming weeks while ( scalar(@weeks) < 6 ) { my @days = (); for $weekday ( 1 .. 7 ) { push @days, sprintf( "%04d-%02d-%02d", $year, $month, $day ); $day++; } push @weeks, \@days; } return \@weeks; } sub check_params($$) { my ($config, $params) = @_; #get start and stop from projects my $range = project::get_date_range($config); my $start_date = $range->{start_date}; my $end_date = $range->{end_date}; #switch off limiting end date by project my $open_end = 0; if ( ( defined $params->{'open_end'} ) && ( $params->{'open_end'} =~ /(\d+)/ ) ) { $open_end = $1; $end_date = time::add_days_to_datetime( time::time_to_datetime(), 365 ); } my $month_only = $params->{month_only} || ''; #filter for date my $date = time::check_date( $params->{date} ); $date = $start_date if ( $date lt $start_date ); $date = $end_date if ( $date gt $end_date ); log::error( $config, "no valid year-month format given!" ) if ( $date eq "-1" ); my $time = time::check_time( $params->{time} ); log::error( $config, "no valid time format given!" ) if ( $time eq "-1" ); my $from_date = time::check_date( $params->{from_date} ) || ''; log::error( $config, "no valid date format given!" ) if ( defined $from_date && $from_date eq "-1" ); $from_date = $start_date if ( $from_date lt $start_date ); $from_date = $end_date if ( $from_date gt $end_date ); my $till_date = time::check_date( $params->{till_date} || '' ); log::error( $config, "no valid date format given!" ) if ( defined $till_date && $till_date eq "-1" ); $till_date = $start_date if ( $till_date lt $start_date ); $till_date = $end_date if ( $till_date gt $end_date ); my $template = template::check( $config, $params->{template}, 'calendar.html' ); return { template => $template, date => $date, from_date => $from_date, till_date => $till_date, month_only => $month_only, open_end => $open_end, start_date => $start_date, end_date => $end_date }; } #do not delete last line! 1;