2014-10-17 15:05:00 +02:00
#!/usr/bin/perl
2007-10-23 02:02:53 +02:00
# Copyright (c) 2006, 2007 Manoj Srivastava <srivasta@debian.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
2012-02-08 21:07:20 +01:00
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
2007-10-23 02:02:53 +02:00
require 5.002 ;
package IkiWiki::Plugin::calendar ;
use warnings ;
use strict ;
2008-12-23 22:34:19 +01:00
use IkiWiki 3.00 ;
2007-10-23 02:02:53 +02:00
use Time::Local ;
2007-12-09 05:54:34 +01:00
my $ time = time ;
my @ now = localtime ( $ time ) ;
2014-07-07 14:54:10 +02:00
my % changed ;
2007-10-23 02:02:53 +02:00
2008-12-17 21:22:16 +01:00
sub import {
2014-06-18 18:38:33 +02:00
hook ( type = > "checkconfig" , id = > "calendar" , call = > \ & checkconfig ) ;
2008-07-27 01:05:52 +02:00
hook ( type = > "getsetup" , id = > "calendar" , call = > \ & getsetup ) ;
hook ( type = > "needsbuild" , id = > "calendar" , call = > \ & needsbuild ) ;
2007-10-23 02:02:53 +02:00
hook ( type = > "preprocess" , id = > "calendar" , call = > \ & preprocess ) ;
2014-06-18 18:38:33 +02:00
hook ( type = > "scan" , id = > "calendar" , call = > \ & scan ) ;
2014-07-07 14:54:10 +02:00
hook ( type = > "build_affected" , id = > "calendar" , call = > \ & build_affected ) ;
2014-07-07 09:40:53 +02:00
IkiWiki:: loadplugin ( "transient" ) ;
2008-12-17 21:22:16 +01:00
}
2007-10-23 02:02:53 +02:00
2008-12-17 21:22:16 +01:00
sub getsetup () {
2008-07-26 00:05:55 +02:00
return
2008-08-03 22:40:12 +02:00
plugin = > {
safe = > 1 ,
rebuild = > undef ,
2010-02-12 12:35:52 +01:00
section = > "widget" ,
2008-08-03 22:40:12 +02:00
} ,
2008-07-26 00:05:55 +02:00
archivebase = > {
type = > "string" ,
2008-07-27 03:07:15 +02:00
example = > "archives" ,
2008-07-26 00:05:55 +02:00
description = > "base of the archives hierarchy" ,
safe = > 1 ,
rebuild = > 1 ,
} ,
2010-04-15 19:40:53 +02:00
archive_pagespec = > {
type = > "pagespec" ,
2010-06-15 19:38:19 +02:00
example = > "page(posts/*) and !*/Discussion" ,
2014-06-18 18:38:33 +02:00
description = > "PageSpec of pages to include in the archives, if option `calendar_autocreate` is true." ,
2010-04-15 19:40:53 +02:00
link = > 'ikiwiki/PageSpec' ,
safe = > 1 ,
rebuild = > 0 ,
} ,
2014-06-18 18:38:33 +02:00
calendar_autocreate = > {
type = > "boolean" ,
example = > 1 ,
description = > "autocreate new calendar pages?" ,
safe = > 1 ,
rebuild = > undef ,
} ,
2014-07-05 14:14:57 +02:00
calendar_fill_gaps = > {
type = > "boolean" ,
example = > 1 ,
default = > 1 ,
description = > "if set, when building calendar pages, also build pages of year and month when no pages were published (building empty calendars)." ,
safe = > 1 ,
rebuild = > 0 ,
} ,
2014-06-18 18:38:33 +02:00
}
sub checkconfig () {
if ( ! defined $ config { calendar_autocreate } ) {
2014-07-07 09:40:53 +02:00
$ config { calendar_autocreate } = defined $ config { archivebase } ;
2014-06-18 18:38:33 +02:00
}
if ( ! defined $ config { archive_pagespec } ) {
$ config { archive_pagespec } = '*' ;
}
if ( ! defined $ config { archivebase } ) {
$ config { archivebase } = 'archives' ;
}
2014-07-05 14:14:57 +02:00
if ( ! defined $ config { calendar_fill_gaps } ) {
$ config { calendar_fill_gaps } = 1 ;
}
2008-12-17 21:22:16 +01:00
}
2008-07-26 00:05:55 +02:00
2008-12-17 21:22:16 +01:00
sub is_leap_year (@) {
2007-10-23 02:02:53 +02:00
my % params = @ _ ;
return ( $ params { year } % 4 == 0 && ( ( $ params { year } % 100 != 0 ) || $ params { year } % 400 == 0 ) ) ;
2008-12-17 21:22:16 +01:00
}
2007-10-23 02:02:53 +02:00
2008-12-17 21:22:16 +01:00
sub month_days {
2007-10-23 02:02:53 +02:00
my % params = @ _ ;
my $ days_in_month = ( 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ) [ $ params { month } - 1 ] ;
if ( $ params { month } == 2 && is_leap_year ( % params ) ) {
$ days_in_month + + ;
}
return $ days_in_month ;
2008-12-17 21:22:16 +01:00
}
2007-10-23 02:02:53 +02:00
2014-07-07 14:54:10 +02:00
sub build_affected {
my % affected ;
2014-11-14 12:50:17 +01:00
my ( $ ayear , $ amonth , $ valid ) ;
foreach my $ year ( keys % changed ) {
( $ ayear , $ valid ) = nextyear ( $ year , $ config { archivebase } ) ;
$ affected { calendarlink ( $ ayear ) } = sprintf ( gettext ( "building calendar for %s, its previous or next year has changed" ) , $ ayear ) if ( $ valid ) ;
( $ ayear , $ valid ) = previousyear ( $ year , $ config { archivebase } ) ;
$ affected { calendarlink ( $ ayear ) } = sprintf ( gettext ( "building calendar for %s, its previous or next year has changed" ) , $ ayear ) if ( $ valid ) ;
2014-12-27 22:55:12 +01:00
foreach my $ month ( keys % { $ changed { $ year } } ) {
2014-11-14 12:50:17 +01:00
( $ ayear , $ amonth , $ valid ) = nextmonth ( $ year , $ month , $ config { archivebase } ) ;
$ affected { calendarlink ( $ ayear , sprintf ( "%02d" , $ amonth ) ) } = sprintf ( gettext ( "building calendar for %s/%s, its previous or next month has changed" ) , $ amonth , $ ayear ) if ( $ valid ) ;
( $ ayear , $ amonth , $ valid ) = previousmonth ( $ year , $ month , $ config { archivebase } ) ;
$ affected { calendarlink ( $ ayear , sprintf ( "%02d" , $ amonth ) ) } = sprintf ( gettext ( "building calendar for %s/%s, its previous or next month has changed" ) , $ amonth , $ ayear ) if ( $ valid ) ;
}
}
2014-07-07 14:54:10 +02:00
return % affected ;
}
2014-06-18 18:38:33 +02:00
sub autocreate {
my ( $ page , $ pagefile , $ year , $ month ) = @ _ ;
my $ message = sprintf ( gettext ( "creating calendar page %s" ) , $ page ) ;
debug ( $ message ) ;
my $ template ;
if ( defined $ month ) {
$ template = template ( "calendarmonth.tmpl" ) ;
} else {
$ template = template ( "calendaryear.tmpl" ) ;
}
$ template - > param ( year = > $ year ) ;
$ template - > param ( month = > $ month ) if defined $ month ;
$ template - > param ( pagespec = > $ config { archive_pagespec } ) ;
2014-07-07 09:40:53 +02:00
my $ dir = $ IkiWiki:: Plugin:: transient:: transientdir ;
2014-06-18 18:38:33 +02:00
writefile ( $ pagefile , $ dir , $ template - > output ) ;
}
sub calendarlink ($;$) {
my ( $ year , $ month ) = @ _ ;
if ( defined $ month ) {
return $ config { archivebase } . "/" . $ year . "/" . $ month ;
} else {
return $ config { archivebase } . "/" . $ year ;
}
}
2014-07-05 14:14:57 +02:00
sub gencalendarmonth {
my $ year = shift ;
my $ month = sprintf ( "%02d" , shift ) ;
my $ page = calendarlink ( $ year , $ month ) ;
my $ pagefile = newpagefile ( $ page , $ config { default_pageext } ) ;
add_autofile (
$ pagefile , "calendar" ,
sub { return autocreate ( $ page , $ pagefile , $ year , $ month ) ; }
) ;
}
2014-06-18 18:38:33 +02:00
sub gencalendaryear {
my $ year = shift ;
2014-07-05 12:11:18 +02:00
my % params = @ _ ;
2014-06-18 18:38:33 +02:00
2014-07-05 12:11:18 +02:00
# Building year page
my $ page = calendarlink ( $ year ) ;
my $ pagefile = newpagefile ( $ page , $ config { default_pageext } ) ;
add_autofile (
$ pagefile , "calendar" ,
sub { return autocreate ( $ page , $ pagefile , $ year ) ; }
) ;
if ( not exists $ wikistate { calendar } { minyear } ) {
$ wikistate { calendar } { minyear } = $ year ;
}
if ( not exists $ wikistate { calendar } { maxyear } ) {
$ wikistate { calendar } { maxyear } = $ year ;
2014-07-05 14:14:57 +02:00
}
if ( $ config { calendar_fill_gaps } ) {
# Building month pages
foreach my $ month ( 1 .. 12 ) {
gencalendarmonth ( $ year , $ month ) ;
2014-06-18 18:38:33 +02:00
}
2014-07-05 14:14:57 +02:00
# Filling potential gaps in years (e.g. calendar goes from 2010 to 2014,
2014-11-26 10:23:24 +01:00
# and we just added year 2005. We have to add years 2006 to 2009).
2014-07-05 14:14:57 +02:00
return if $ params { norecurse } ;
if ( $ wikistate { calendar } { minyear } > $ year ) {
foreach my $ other ( $ year + 1 .. $ wikistate { calendar } { minyear } - 1 ) {
gencalendaryear ( $ other , norecurse = > 1 ) ;
}
$ wikistate { calendar } { minyear } = $ year ;
}
if ( $ wikistate { calendar } { maxyear } < $ year ) {
foreach my $ other ( $ wikistate { calendar } { maxyear } + 1 .. $ year - 1 ) {
gencalendaryear ( $ other , norecurse = > 1 ) ;
}
$ wikistate { calendar } { maxyear } = $ year ;
}
}
if ( $ year < $ wikistate { calendar } { minyear } ) {
$ wikistate { calendar } { minyear } = $ year ;
}
if ( $ year > $ wikistate { calendar } { maxyear } ) {
2014-07-05 12:11:18 +02:00
$ wikistate { calendar } { maxyear } = $ year ;
2014-06-18 18:38:33 +02:00
}
}
2014-07-07 14:54:10 +02:00
sub previousmonth ($$$) {
2014-11-14 12:50:17 +01:00
my $ year = shift ;
my $ month = shift ;
my $ archivebase = shift ;
2014-07-07 14:54:10 +02:00
2014-11-26 12:29:14 +01:00
if ( not exists $ wikistate { calendar } { minyear } ) {
$ wikistate { calendar } { minyear } = $ year ;
}
2014-07-07 14:54:10 +02:00
my $ pmonth = $ month ;
my $ pyear = $ year ;
while ( ( not exists $ pagesources { "$archivebase/$pyear/" . sprintf ( "%02d" , $ pmonth ) } ) or ( $ pmonth == $ month and $ pyear == $ year ) ) {
$ pmonth -= 1 ;
if ( $ pmonth == 0 ) {
$ pyear -= 1 ;
$ pmonth = 12 ;
2014-11-14 12:50:17 +01:00
return ( $ pyear , $ pmonth , 0 ) unless $ pyear >= $ wikistate { calendar } { minyear } ;
2014-07-07 14:54:10 +02:00
}
}
2014-11-14 12:50:17 +01:00
return ( $ pyear , $ pmonth , 1 ) ;
2014-07-07 14:54:10 +02:00
}
sub nextmonth ($$$) {
2014-11-14 12:50:17 +01:00
my $ year = shift ;
my $ month = shift ;
my $ archivebase = shift ;
2014-07-07 14:54:10 +02:00
2014-11-26 12:29:14 +01:00
if ( not exists $ wikistate { calendar } { maxyear } ) {
$ wikistate { calendar } { maxyear } = $ year ;
}
2014-07-07 14:54:10 +02:00
my $ nmonth = $ month ;
my $ nyear = $ year ;
while ( ( not exists $ pagesources { "$archivebase/$nyear/" . sprintf ( "%02d" , $ nmonth ) } ) or ( $ nmonth == $ month and $ nyear == $ year ) ) {
$ nmonth += 1 ;
if ( $ nmonth == 13 ) {
$ nyear += 1 ;
$ nmonth = 1 ;
2014-11-14 12:50:17 +01:00
return ( $ nyear , $ nmonth , 0 ) unless $ nyear <= $ wikistate { calendar } { maxyear } ;
2014-07-07 14:54:10 +02:00
}
}
2014-11-14 12:50:17 +01:00
return ( $ nyear , $ nmonth , 1 ) ;
2014-07-07 14:54:10 +02:00
}
sub previousyear ($$) {
2014-11-14 12:50:17 +01:00
my $ year = shift ;
my $ archivebase = shift ;
my $ pyear = $ year - 1 ;
while ( not exists $ pagesources { "$archivebase/$pyear" } ) {
$ pyear -= 1 ;
return ( $ pyear , 0 ) unless ( $ pyear >= $ wikistate { calendar } { minyear } ) ;
}
return ( $ pyear , 1 ) ;
2014-07-07 14:54:10 +02:00
}
sub nextyear ($$) {
2014-11-14 12:50:17 +01:00
my $ year = shift ;
my $ archivebase = shift ;
my $ nyear = $ year + 1 ;
while ( not exists $ pagesources { "$archivebase/$nyear" } ) {
$ nyear += 1 ;
return ( $ nyear , 0 ) unless ( $ nyear <= $ wikistate { calendar } { maxyear } ) ;
}
return ( $ nyear , 1 ) ;
2014-07-07 14:54:10 +02:00
}
2008-12-17 21:22:16 +01:00
sub format_month (@) {
2007-10-23 02:02:53 +02:00
my % params = @ _ ;
2009-10-09 05:24:03 +02:00
my % linkcache ;
2009-10-12 18:30:10 +02:00
foreach my $ p ( pagespec_match_list ( $ params { page } ,
"creation_year($params{year}) and creation_month($params{month}) and ($params{pages})" ,
2009-10-09 05:24:03 +02:00
# add presence dependencies to update
# month calendar when pages are added/removed
deptype = > deptype ( "presence" ) ) ) {
my $ mtime = $ IkiWiki:: pagectime { $ p } ;
my @ date = localtime ( $ mtime ) ;
my $ mday = $ date [ 3 ] ;
my $ month = $ date [ 4 ] + 1 ;
my $ year = $ date [ 5 ] + 1900 ;
my $ mtag = sprintf ( "%02d" , $ month ) ;
2013-06-23 20:11:39 +02:00
if ( ! $ linkcache { "$year/$mtag/$mday" } ) {
$ linkcache { "$year/$mtag/$mday" } = [] ;
}
push ( @ { $ linkcache { "$year/$mtag/$mday" } } , $ p ) ;
2009-10-09 05:24:03 +02:00
}
2009-10-12 03:42:59 +02:00
2014-07-05 14:14:57 +02:00
my $ archivebase = 'archives' ;
$ archivebase = $ config { archivebase } if defined $ config { archivebase } ;
$ archivebase = $ params { archivebase } if defined $ params { archivebase } ;
2014-11-14 12:50:17 +01:00
my ( $ pyear , $ pmonth , $ pvalid ) = previousmonth ( $ params { year } , $ params { month } , $ archivebase ) ;
my ( $ nyear , $ nmonth , $ nvalid ) = nextmonth ( $ params { year } , $ params { month } , $ archivebase ) ;
2009-10-09 05:24:03 +02:00
2009-10-12 03:52:50 +02:00
# Add padding.
$ pmonth = sprintf ( "%02d" , $ pmonth ) ;
$ nmonth = sprintf ( "%02d" , $ nmonth ) ;
2007-10-23 02:02:53 +02:00
my $ calendar = "\n" ;
# When did this month start?
2009-10-12 02:15:54 +02:00
my @ monthstart = localtime ( timelocal ( 0 , 0 , 0 , 1 , $ params { month } - 1 , $ params { year } - 1900 ) ) ;
2007-10-23 02:02:53 +02:00
my $ future_dom = 0 ;
my $ today = 0 ;
2009-10-12 02:15:54 +02:00
if ( $ params { year } == $ now [ 5 ] + 1900 && $ params { month } == $ now [ 4 ] + 1 ) {
2007-10-23 02:02:53 +02:00
$ future_dom = $ now [ 3 ] + 1 ;
$ today = $ now [ 3 ] ;
}
# Find out month names for this, next, and previous months
2012-01-30 20:08:50 +01:00
my $ monthabbrev = strftime_utf8 ( "%b" , @ monthstart ) ;
my $ monthname = strftime_utf8 ( "%B" , @ monthstart ) ;
my $ pmonthname = strftime_utf8 ( "%B" , localtime ( timelocal ( 0 , 0 , 0 , 1 , $ pmonth - 1 , $ pyear - 1900 ) ) ) ;
my $ nmonthname = strftime_utf8 ( "%B" , localtime ( timelocal ( 0 , 0 , 0 , 1 , $ nmonth - 1 , $ nyear - 1900 ) ) ) ;
2007-10-23 02:02:53 +02:00
# Calculate URL's for monthly archives.
2010-05-08 19:51:05 +02:00
my ( $ url , $ purl , $ nurl ) = ( "$monthname $params{year}" , '' , '' ) ;
2009-10-12 02:15:54 +02:00
if ( exists $ pagesources { "$archivebase/$params{year}/$params{month}" } ) {
2007-10-23 02:02:53 +02:00
$ url = htmllink ( $ params { page } , $ params { destpage } ,
2009-10-12 03:52:50 +02:00
"$archivebase/$params{year}/" . $ params { month } ,
2009-10-12 04:11:11 +02:00
noimageinline = > 1 ,
2010-06-10 21:01:10 +02:00
linktext = > "$monthabbrev $params{year}" ,
2009-11-26 20:57:52 +01:00
title = > $ monthname ) ;
2007-10-23 02:02:53 +02:00
}
2009-10-12 03:52:50 +02:00
add_depends ( $ params { page } , "$archivebase/$params{year}/$params{month}" ,
2009-10-08 22:49:03 +02:00
deptype ( "presence" ) ) ;
2009-10-12 03:42:59 +02:00
if ( exists $ pagesources { "$archivebase/$pyear/$pmonth" } ) {
2007-10-23 02:02:53 +02:00
$ purl = htmllink ( $ params { page } , $ params { destpage } ,
2009-10-12 03:52:50 +02:00
"$archivebase/$pyear/$pmonth" ,
2009-10-12 04:11:11 +02:00
noimageinline = > 1 ,
2010-01-02 19:22:25 +01:00
linktext = > "\←" ,
2009-11-26 20:57:52 +01:00
title = > $ pmonthname ) ;
2007-10-23 02:02:53 +02:00
}
2009-10-12 03:52:50 +02:00
add_depends ( $ params { page } , "$archivebase/$pyear/$pmonth" ,
2009-10-08 22:49:03 +02:00
deptype ( "presence" ) ) ;
2009-10-12 03:42:59 +02:00
if ( exists $ pagesources { "$archivebase/$nyear/$nmonth" } ) {
2007-10-23 02:02:53 +02:00
$ nurl = htmllink ( $ params { page } , $ params { destpage } ,
2009-10-12 03:52:50 +02:00
"$archivebase/$nyear/$nmonth" ,
2009-10-12 04:11:11 +02:00
noimageinline = > 1 ,
2010-01-02 19:22:25 +01:00
linktext = > "\→" ,
2009-11-26 20:57:52 +01:00
title = > $ nmonthname ) ;
2007-10-23 02:02:53 +02:00
}
2009-10-12 03:52:50 +02:00
add_depends ( $ params { page } , "$archivebase/$nyear/$nmonth" ,
2009-10-08 22:49:03 +02:00
deptype ( "presence" ) ) ;
2007-10-23 02:02:53 +02:00
# Start producing the month calendar
$ calendar = << EOF ;
< table class = "month-calendar" >
2010-04-16 02:12:03 +02:00
<tr>
< th class = "month-calendar-arrow" > $ purl </th>
< th class = "month-calendar-head" colspan = "5" > $ url </th>
< th class = "month-calendar-arrow" > $ nurl </th>
</tr>
2007-10-23 02:02:53 +02:00
<tr>
EOF
# Suppose we want to start the week with day $week_start_day
# If $monthstart[6] == 1
my $ week_start_day = $ params { week_start_day } ;
my $ start_day = 1 + ( 7 - $ monthstart [ 6 ] + $ week_start_day ) % 7 ;
my % downame ;
my % dowabbr ;
for my $ dow ( $ week_start_day .. $ week_start_day + 6 ) {
2009-10-12 02:15:54 +02:00
my @ day = localtime ( timelocal ( 0 , 0 , 0 , $ start_day + + , $ params { month } - 1 , $ params { year } - 1900 ) ) ;
2012-01-30 20:08:50 +01:00
my $ downame = strftime_utf8 ( "%A" , @ day ) ;
2010-06-10 21:01:10 +02:00
my $ dowabbr = substr ( $ downame , 0 , 1 ) ;
2007-10-23 02:02:53 +02:00
$ downame { $ dow % 7 } = $ downame ;
$ dowabbr { $ dow % 7 } = $ dowabbr ;
2009-11-26 20:57:52 +01:00
$ calendar . = qq{ \ t \ t<th class="month-calendar-day-head $downame" title="$downame">$dowabbr</th> \ n } ;
2007-10-23 02:02:53 +02:00
}
$ calendar . = << EOF ;
</tr>
EOF
my $ wday ;
# we start with a week_start_day, and skip until we get to the first
for ( $ wday = $ week_start_day ; $ wday != $ monthstart [ 6 ] ; $ wday + + , $ wday % = 7 ) {
$ calendar . = qq{ \ t<tr> \ n } if $ wday == $ week_start_day ;
$ calendar . = qq{ \ t \ t<td class="month-calendar-day-noday $downame { $wday } "> </td> \ n } ;
}
# At this point, either the first is a week_start_day, in which case
# nothing has been printed, or else we are in the middle of a row.
2009-10-12 02:15:54 +02:00
for ( my $ day = 1 ; $ day <= month_days ( year = > $ params { year } , month = > $ params { month } ) ;
2007-10-23 02:02:53 +02:00
$ day + + , $ wday + + , $ wday % = 7 ) {
2009-11-26 20:57:52 +01:00
# At this point, on a week_start_day, we close out a row,
2007-10-23 02:02:53 +02:00
# and start a new one -- unless it is week_start_day on the
# first, where we do not close a row -- since none was started.
if ( $ wday == $ week_start_day ) {
$ calendar . = qq{ \ t</tr> \ n } unless $ day == 1 ;
$ calendar . = qq{ \ t<tr> \ n } ;
}
my $ tag ;
2009-11-26 20:57:52 +01:00
my $ key = "$params{year}/$params{month}/$day" ;
if ( defined $ linkcache { $ key } ) {
2007-10-23 02:02:53 +02:00
if ( $ day == $ today ) {
$ tag = 'month-calendar-day-this-day' ;
}
else {
$ tag = 'month-calendar-day-link' ;
}
$ calendar . = qq{ \ t \ t<td class="$tag $downame { $wday } "> } ;
2013-07-20 00:54:32 +02:00
$ calendar . = qq{ <div class='popup'>$day<div class='balloon'> } ;
# Several postings on this page
$ calendar . = qq{ <ul> } ;
foreach my $ page ( @ { $ linkcache { $ key } } ) {
$ calendar . = qq{ \ n \ t \ t \ t<li> } ;
my $ title ;
if ( exists $ pagestate { $ page } { meta } { title } ) {
$ title = "$pagestate{$page}{meta}{title}" ;
}
else {
$ title = pagetitle ( IkiWiki:: basename ( $ page ) ) ;
}
2013-06-23 20:11:39 +02:00
$ calendar . = htmllink ( $ params { page } , $ params { destpage } ,
$ page ,
noimageinline = > 1 ,
2013-07-20 00:54:32 +02:00
linktext = > $ title ,
title = > $ title ) ;
$ calendar . = '</li>' ;
2013-06-23 20:11:39 +02:00
}
2013-07-20 00:54:32 +02:00
$ calendar . = qq{ \ n \ t \ t</ul> } ;
$ calendar . = qq{ </div></div> } ;
2007-10-23 02:02:53 +02:00
$ calendar . = qq{ </td> \ n } ;
}
else {
if ( $ day == $ today ) {
$ tag = 'month-calendar-day-this-day' ;
}
elsif ( $ day == $ future_dom ) {
$ tag = 'month-calendar-day-future' ;
}
else {
$ tag = 'month-calendar-day-nolink' ;
}
$ calendar . = qq{ \ t \ t<td class="$tag $downame { $wday } ">$day</td> \ n } ;
}
}
# finish off the week
for ( ; $ wday != $ week_start_day ; $ wday + + , $ wday % = 7 ) {
$ calendar . = qq{ \ t \ t<td class="month-calendar-day-noday $downame { $wday } "> </td> \ n } ;
}
$ calendar . = << EOF ;
</tr>
</table>
EOF
return $ calendar ;
2008-12-17 21:22:16 +01:00
}
2007-10-23 02:02:53 +02:00
2008-12-17 21:22:16 +01:00
sub format_year (@) {
2007-10-23 02:02:53 +02:00
my % params = @ _ ;
2014-06-18 18:38:33 +02:00
2009-10-12 20:19:04 +02:00
my @ post_months ;
foreach my $ p ( pagespec_match_list ( $ params { page } ,
"creation_year($params{year}) and ($params{pages})" ,
# add presence dependencies to update
# year calendar's links to months when
# pages are added/removed
deptype = > deptype ( "presence" ) ) ) {
my $ mtime = $ IkiWiki:: pagectime { $ p } ;
my @ date = localtime ( $ mtime ) ;
my $ month = $ date [ 4 ] + 1 ;
$ post_months [ $ month ] + + ;
}
2009-10-12 03:42:59 +02:00
2007-10-23 02:02:53 +02:00
my $ calendar = "\n" ;
2014-07-05 14:14:57 +02:00
my $ archivebase = 'archives' ;
$ archivebase = $ config { archivebase } if defined $ config { archivebase } ;
$ archivebase = $ params { archivebase } if defined $ params { archivebase } ;
2009-10-12 03:42:59 +02:00
2014-11-14 12:50:17 +01:00
my ( $ pyear , $ pvalid ) = previousyear ( $ params { year } , $ archivebase ) ;
my ( $ nyear , $ nvalid ) = nextyear ( $ params { year } , $ archivebase ) ;
2007-10-23 02:02:53 +02:00
2009-10-12 20:22:48 +02:00
my $ thisyear = $ now [ 5 ] + 1900 ;
2007-10-23 02:02:53 +02:00
my $ future_month = 0 ;
2009-10-12 20:22:48 +02:00
$ future_month = $ now [ 4 ] + 1 if $ params { year } == $ thisyear ;
2007-10-23 02:02:53 +02:00
# calculate URL's for previous and next years
2009-10-12 02:15:54 +02:00
my ( $ url , $ purl , $ nurl ) = ( "$params{year}" , '' , '' ) ;
if ( exists $ pagesources { "$archivebase/$params{year}" } ) {
2007-10-23 02:02:53 +02:00
$ url = htmllink ( $ params { page } , $ params { destpage } ,
2009-10-12 02:15:54 +02:00
"$archivebase/$params{year}" ,
2009-10-12 04:11:11 +02:00
noimageinline = > 1 ,
2009-11-26 20:57:52 +01:00
linktext = > $ params { year } ,
title = > $ params { year } ) ;
2007-10-23 02:02:53 +02:00
}
2009-10-12 02:15:54 +02:00
add_depends ( $ params { page } , "$archivebase/$params{year}" , deptype ( "presence" ) ) ;
2009-10-12 03:42:59 +02:00
if ( exists $ pagesources { "$archivebase/$pyear" } ) {
2007-10-23 02:02:53 +02:00
$ purl = htmllink ( $ params { page } , $ params { destpage } ,
2009-10-12 03:42:59 +02:00
"$archivebase/$pyear" ,
2009-10-12 04:11:11 +02:00
noimageinline = > 1 ,
2009-11-26 20:57:52 +01:00
linktext = > "\←" ,
title = > $ pyear ) ;
2007-10-23 02:02:53 +02:00
}
2009-10-12 03:42:59 +02:00
add_depends ( $ params { page } , "$archivebase/$pyear" , deptype ( "presence" ) ) ;
if ( exists $ pagesources { "$archivebase/$nyear" } ) {
2007-10-23 02:02:53 +02:00
$ nurl = htmllink ( $ params { page } , $ params { destpage } ,
2009-10-12 03:42:59 +02:00
"$archivebase/$nyear" ,
2009-10-12 04:11:11 +02:00
noimageinline = > 1 ,
2009-11-26 20:57:52 +01:00
linktext = > "\→" ,
title = > $ nyear ) ;
2007-10-23 02:02:53 +02:00
}
2009-10-12 03:42:59 +02:00
add_depends ( $ params { page } , "$archivebase/$nyear" , deptype ( "presence" ) ) ;
2007-10-23 02:02:53 +02:00
# Start producing the year calendar
2010-04-16 02:12:03 +02:00
my $ m = $ params { months_per_row } - 2 ;
2007-10-23 02:02:53 +02:00
$ calendar = << EOF ;
< table class = "year-calendar" >
2010-04-16 02:12:03 +02:00
<tr>
< th class = "year-calendar-arrow" > $ purl </th>
< th class = "year-calendar-head" colspan = "$m" > $ url </th>
< th class = "year-calendar-arrow" > $ nurl </th>
</tr>
2007-10-23 02:02:53 +02:00
<tr>
< th class = "year-calendar-subhead" colspan = "$params{months_per_row}" > Months </th>
</tr>
EOF
2009-10-12 02:15:54 +02:00
for ( my $ month = 1 ; $ month <= 12 ; $ month + + ) {
my @ day = localtime ( timelocal ( 0 , 0 , 0 , 15 , $ month - 1 , $ params { year } - 1900 ) ) ;
2007-10-23 02:02:53 +02:00
my $ murl ;
2012-01-30 20:08:50 +01:00
my $ monthname = strftime_utf8 ( "%B" , @ day ) ;
my $ monthabbr = strftime_utf8 ( "%b" , @ day ) ;
2007-10-23 02:02:53 +02:00
$ calendar . = qq{ \ t<tr> \ n } if ( $ month % $ params { months_per_row } == 1 ) ;
my $ tag ;
my $ mtag = sprintf ( "%02d" , $ month ) ;
2009-10-12 20:22:48 +02:00
if ( $ month == $ params { month } && $ thisyear == $ params { year } ) {
2009-10-12 18:19:42 +02:00
$ tag = 'year-calendar-this-month' ;
2007-10-23 02:02:53 +02:00
}
2009-10-12 02:15:54 +02:00
elsif ( $ pagesources { "$archivebase/$params{year}/$mtag" } ) {
2009-10-12 18:19:42 +02:00
$ tag = 'year-calendar-month-link' ;
2007-10-23 02:02:53 +02:00
}
elsif ( $ future_month && $ month >= $ future_month ) {
2009-10-12 18:19:42 +02:00
$ tag = 'year-calendar-month-future' ;
2007-10-23 02:02:53 +02:00
}
else {
2009-10-12 18:19:42 +02:00
$ tag = 'year-calendar-month-nolink' ;
2007-10-23 02:02:53 +02:00
}
2009-10-12 20:19:04 +02:00
if ( $ pagesources { "$archivebase/$params{year}/$mtag" } &&
$ post_months [ $ mtag ] ) {
2007-10-23 02:02:53 +02:00
$ murl = htmllink ( $ params { page } , $ params { destpage } ,
2009-10-12 02:15:54 +02:00
"$archivebase/$params{year}/$mtag" ,
2009-10-12 04:11:11 +02:00
noimageinline = > 1 ,
2009-11-26 20:57:52 +01:00
linktext = > $ monthabbr ,
title = > $ monthname ) ;
2007-10-23 02:02:53 +02:00
$ calendar . = qq{ \ t<td class="$tag"> } ;
$ calendar . = $ murl ;
$ calendar . = qq{ \ t</td> \ n } ;
}
else {
$ calendar . = qq{ \ t<td class="$tag">$monthabbr</td> \ n } ;
}
2009-10-12 02:15:54 +02:00
add_depends ( $ params { page } , "$archivebase/$params{year}/$mtag" ,
2009-10-08 22:49:03 +02:00
deptype ( "presence" ) ) ;
2007-10-23 02:02:53 +02:00
$ calendar . = qq{ \ t</tr> \ n } if ( $ month % $ params { months_per_row } == 0 ) ;
}
$ calendar . = << EOF ;
</table>
EOF
return $ calendar ;
2008-12-17 21:22:16 +01:00
}
2007-10-23 02:02:53 +02:00
2010-05-08 18:52:19 +02:00
sub setnextchange ($$) {
my $ page = shift ;
my $ timestamp = shift ;
if ( ! exists $ pagestate { $ page } { calendar } { nextchange } ||
$ pagestate { $ page } { calendar } { nextchange } > $ timestamp ) {
$ pagestate { $ page } { calendar } { nextchange } = $ timestamp ;
}
}
2008-12-17 21:22:16 +01:00
sub preprocess (@) {
2007-10-23 02:02:53 +02:00
my % params = @ _ ;
2009-10-12 03:06:10 +02:00
my $ thisyear = 1900 + $ now [ 5 ] ;
my $ thismonth = 1 + $ now [ 4 ] ;
2007-10-23 02:02:53 +02:00
$ params { pages } = "*" unless defined $ params { pages } ;
$ params { type } = "month" unless defined $ params { type } ;
$ params { week_start_day } = 0 unless defined $ params { week_start_day } ;
$ params { months_per_row } = 3 unless defined $ params { months_per_row } ;
2009-10-12 03:06:10 +02:00
$ params { year } = $ thisyear unless defined $ params { year } ;
$ params { month } = $ thismonth unless defined $ params { month } ;
2010-05-08 18:45:21 +02:00
my $ relativeyear = 0 ;
if ( $ params { year } < 1 ) {
$ relativeyear = 1 ;
2010-05-08 19:51:05 +02:00
$ params { year } = $ thisyear + $ params { year } ;
}
my $ relativemonth = 0 ;
if ( $ params { month } < 1 ) {
$ relativemonth = 1 ;
my $ monthoff = $ params { month } ;
$ params { month } = ( $ thismonth + $ monthoff ) % 12 ;
$ params { month } = 12 if $ params { month } == 0 ;
my $ yearoff = POSIX:: ceil ( ( $ thismonth - $ params { month } ) / - 12 )
- int ( $ monthoff / 12 ) ;
$ params { year } -= $ yearoff ;
2010-05-08 18:45:21 +02:00
}
2009-10-12 03:06:10 +02:00
$ params { month } = sprintf ( "%02d" , $ params { month } ) ;
2014-11-14 12:50:17 +01:00
$ changed { $ params { year } } { $ params { month } } = 1 ;
2010-05-08 18:45:21 +02:00
2009-10-12 03:06:10 +02:00
if ( $ params { type } eq 'month' && $ params { year } == $ thisyear
&& $ params { month } == $ thismonth ) {
# calendar for current month, updates next midnight
2010-05-08 18:52:19 +02:00
setnextchange ( $ params { destpage } , ( $ time
2007-12-09 05:54:34 +01:00
+ ( 60 - $ now [ 0 ] ) # seconds
+ ( 59 - $ now [ 1 ] ) * 60 # minutes
+ ( 23 - $ now [ 2 ] ) * 60 * 60 # hours
2010-05-08 18:52:19 +02:00
) ) ;
2009-10-12 03:06:10 +02:00
}
elsif ( $ params { type } eq 'month' &&
( ( $ params { year } == $ thisyear && $ params { month } > $ thismonth ) ||
$ params { year } > $ thisyear ) ) {
# calendar for upcoming month, updates 1st of that month
2010-05-08 18:52:19 +02:00
setnextchange ( $ params { destpage } ,
timelocal ( 0 , 0 , 0 , 1 , $ params { month } - 1 , $ params { year } ) ) ;
2009-10-12 03:06:10 +02:00
}
2010-05-08 18:45:21 +02:00
elsif ( ( $ params { type } eq 'year' && $ params { year } == $ thisyear ) ||
$ relativemonth ) {
# Calendar for current year updates 1st of next month.
# Any calendar relative to the current month also updates
# then.
2009-12-02 18:58:45 +01:00
if ( $ thismonth < 12 ) {
2010-05-08 18:52:19 +02:00
setnextchange ( $ params { destpage } ,
timelocal ( 0 , 0 , 0 , 1 , $ thismonth + 1 - 1 , $ params { year } ) ) ;
2009-12-02 18:58:45 +01:00
}
else {
2010-05-08 18:52:19 +02:00
setnextchange ( $ params { destpage } ,
timelocal ( 0 , 0 , 0 , 1 , 1 - 1 , $ params { year } + 1 ) ) ;
2009-12-02 18:58:45 +01:00
}
2009-10-12 03:06:10 +02:00
}
2010-05-08 18:45:21 +02:00
elsif ( $ relativeyear ) {
# Any calendar relative to the current year updates 1st
# of next year.
2010-05-08 18:52:19 +02:00
setnextchange ( $ params { destpage } ,
timelocal ( 0 , 0 , 0 , 1 , 1 - 1 , $ thisyear + 1 ) ) ;
2010-05-08 18:45:21 +02:00
}
2009-10-12 03:06:10 +02:00
elsif ( $ params { type } eq 'year' && $ params { year } > $ thisyear ) {
# calendar for upcoming year, updates 1st of that year
2010-05-08 18:52:19 +02:00
setnextchange ( $ params { destpage } ,
timelocal ( 0 , 0 , 0 , 1 , 1 - 1 , $ params { year } ) ) ;
2007-12-09 05:54:34 +01:00
}
else {
2009-10-12 03:06:10 +02:00
# calendar for past month or year, does not need
# to update any more
2007-12-09 05:54:34 +01:00
delete $ pagestate { $ params { destpage } } { calendar } ;
}
2009-10-12 02:15:54 +02:00
my $ calendar = "" ;
2009-10-12 03:06:10 +02:00
if ( $ params { type } eq 'month' ) {
2007-10-23 02:02:53 +02:00
$ calendar = format_month ( % params ) ;
}
2009-10-12 03:06:10 +02:00
elsif ( $ params { type } eq 'year' ) {
2007-10-23 02:02:53 +02:00
$ calendar = format_year ( % params ) ;
}
2007-12-09 05:54:34 +01:00
return "\n<div><div class=\"calendar\">$calendar</div></div>\n" ;
2007-10-23 07:12:18 +02:00
} #}}
2007-10-23 02:02:53 +02:00
2008-12-17 21:22:16 +01:00
sub needsbuild (@) {
2007-12-09 06:05:07 +01:00
my $ needsbuild = shift ;
foreach my $ page ( keys % pagestate ) {
if ( exists $ pagestate { $ page } { calendar } { nextchange } ) {
if ( $ pagestate { $ page } { calendar } { nextchange } <= $ time ) {
# force a rebuild so the calendar shows
# the current day
push @$ needsbuild , $ pagesources { $ page } ;
}
2008-01-29 23:36:25 +01:00
if ( exists $ pagesources { $ page } &&
grep { $ _ eq $ pagesources { $ page } } @$ needsbuild ) {
2007-12-09 06:05:07 +01:00
# remove state, will be re-added if
# the calendar is still there during the
# rebuild
delete $ pagestate { $ page } { calendar } ;
}
}
}
2014-06-18 18:38:33 +02:00
2010-09-07 18:08:59 +02:00
return $ needsbuild ;
2008-12-17 21:22:16 +01:00
}
2007-12-09 06:05:07 +01:00
2014-06-18 18:38:33 +02:00
sub scan (@) {
my % params = @ _ ;
my $ page = $ params { page } ;
2014-11-14 14:59:37 +01:00
return unless $ config { calendar_autocreate } ;
2014-06-18 18:38:33 +02:00
# Check if year pages have to be generated
if ( pagespec_match ( $ page , $ config { archive_pagespec } ) ) {
my @ ctime = localtime ( $ IkiWiki:: pagectime { $ page } ) ;
gencalendaryear ( $ ctime [ 5 ] + 1900 ) ;
2014-07-05 14:14:57 +02:00
gencalendarmonth ( $ ctime [ 5 ] + 1900 , $ ctime [ 4 ] + 1 ) ;
2014-06-18 18:38:33 +02:00
}
}
2007-10-23 02:02:53 +02:00
1