From 2febc6d9b0a2d9d598461aed8a4c284d9ae43bbc Mon Sep 17 00:00:00 2001 From: Gavin Carr Date: Thu, 27 Sep 2007 23:11:11 +0000 Subject: [PATCH] Add storydate. --- gavinc/storydate | 279 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 279 insertions(+) create mode 100644 gavinc/storydate diff --git a/gavinc/storydate b/gavinc/storydate new file mode 100644 index 0000000..0341ea0 --- /dev/null +++ b/gavinc/storydate @@ -0,0 +1,279 @@ +# Blosxom Plugin: storydate +# Author(s): Gavin Carr +# (based on work by Frank Hecker +# and Bob Schumaker ) +# Version: 0.001000 +# Documentation: See the bottom of this file or type: perldoc storydate + +package storydate; + +use strict; + +use File::stat; + +# Uncomment next line to enable debug output (don't uncomment debug() lines) +#use Blosxom::Debug debug_level => 1; + +# --- Configuration variables ----- + +# Perl modules to use for strftime, in search order +my @strftime_modules = qw(Time::Piece Date::Format POSIX); + +# --------------------------------- + +# Package variables +use vars qw( + $story_rfc822 + $story_iso8601 + $story_mtime_rfc822 + $story_mtime_iso8601 + $now_rfc822 + $now_iso8601 + %strftime_formats +); + +%strftime_formats = ( + rfc822 => "%a, %d %b %Y %T %z", + # ISO 8601 format (localtime, including time zone offset) + # Format is YYYY-MM-DDThh:mm:ssTZD per http://www.w3.org/TR/NOTE-datetime + iso8601 => "%Y-%m-%dT%T %z", +); + +sub start { + my $now = time(); + $now_rfc822 = format_date('rfc822', $now); + $now_iso8601 = format_date('iso8601', $now); + # debug(1, "now_rfc822: $now_rfc822"); + # debug(1, "now_iso8601: $now_iso8601"); + 1; +} + +sub story { + my ($pkg, $path, $filename, $story_ref, $title_ref, $body_ref) = @_; + + ($story_rfc822, $story_mtime_rfc822) + = get_story_dates('rfc822', $path, $filename); + ($story_iso8601, $story_mtime_iso8601) + = get_story_dates('iso8601', $path, $filename); + + return 1; +} + +# Get the 'file' (publish/official) and 'mtime' formatted dates for the given story file +sub get_story_dates { + my ($format, $path, $filename) = @_; + my ($file_dt, $mtime_dt) = ('', ''); + $path ||= ''; + + my $story_file = "$blosxom::datadir$path/$filename.$blosxom::file_extension"; + my $timestamp = $blosxom::files{ $story_file }; + # debug(2, "$path/$filename timestamp: $timestamp"); + + if (my $stat = stat( $story_file )) { + if (my $mtime = $stat->mtime) { + # debug(2, "$path/$filename mtime: = $mtime"); + + $mtime_dt = format_date($format, $mtime); + + $timestamp ||= $mtime; + } + else { + warn "storydate: cannot get mtime on story file '$story_file'\n"; + } + } + else { + warn "storydate: cannot stat story file '$story_file'\n"; + } + + $file_dt = format_date($format, $timestamp) if $timestamp; + + return wantarray ? ( $file_dt, $mtime_dt ) : $file_dt; +} + +sub format_date { + my ($format, $time, $use_gmtime) = @_; + return unless $format; + if ($format =~ m/%/) { + return strftime($format, $time, $use_gmtime); + } + elsif ($strftime_formats{ $format }) { + return strftime($strftime_formats{ $format }, $time, $use_gmtime); + } +} + +# strftime wrapper, using the first strftime() it finds in @strftime_modules +my %cache = (); +my $strftime_module = ''; +sub strftime { + my ($format, $time, $use_gmtime) = @_; + return unless $format && $time; + $use_gmtime = 0 unless defined $use_gmtime; + + # Check cache + my $cache_key = "$time:$use_gmtime:$format"; + return $cache{ $cache_key } if exists $cache{ $cache_key }; + + # For testing + $strftime_module = $ENV{BLOSXOM_STORYDATE_STRFTIME_MODULE}; + + # Search for a strftime module, and load + if (! $strftime_module) { + for my $module (@strftime_modules) { + if (eval "require $module") { + $strftime_module = $module; + # debug(2, "strftime_module: $strftime_module"); + last; + } + } + if (! $strftime_module) { + warn "storydate: cannot find any suitable strftime module\n"; + return ''; + } + } + + my $datetime = ''; + if ($strftime_module eq 'Time::Piece') { + my $t = $use_gmtime ? Time::Piece->gmtime($time) : Time::Piece->localtime($time); + + # Seems to be a bug in Time::Piece %z handling - workaround + my $tz_offset = sprintf("%+03d%02d", int($t->tzoffset / 3600), ($t->tzoffset % 3600) / 60); + $format =~ s/%z/$tz_offset/g; + + $datetime = $t->strftime( $format ); + } + + elsif ($strftime_module eq 'Date::Format') { + my @t = $use_gmtime ? gmtime($time) : localtime($time); + $datetime = Date::Format::strftime($format, \@t); + } + + elsif ($strftime_module eq 'POSIX') { + my @t = $use_gmtime ? gmtime($time) : localtime($time); + $datetime = POSIX::strftime($format, @t); + } + + $cache{ $cache_key } = $datetime if $datetime; + return $datetime; +} + + +1; + +__END__ + +=head1 NAME + +storydate - blosxom plugin to provide story dates in various formats +for use by other plugins + + +=head1 DESCRIPTION + +storydate is a blosxom plugin that provides story dates in various +formats for use by other plugins. It defines the following variables: + +=over 4 + +=item $story_rfc822 + +The official/publication date of the story in RFC822 format. + +=item $story_iso8601 + +The official/publication date of the story in ISO8601 format. + +=item $story_mtime_rfc822 + +The last modification time of the story in RFC822 format. + +=item $story_mtime_iso8601 + +The last modification time of the story in ISO8601 format. + +=item $now_rfc822 + +The current time in RFC822 format. + +=item $now_iso8601 + +The current time in ISO8601 format. + +=back + +In addition, storydate defines a few subroutines that might be useful +to other plugins: + +=over 4 + +=item strftime($format, $time) + +Returns $time, formatted according to the L format +$format. Requires one of the following perl modules be available to +provide a strftime() function: Time::Piece, Date::Format, or POSIX. + +=item get_story_dates($format, $path, $filename) + +Returns the publication date and the last modified date of the story +at "$path/$filename.$blosxom::file_extension", formatted according +to the L format $format. + +=back + + +=head1 USAGE + +storydate should be loaded early, before any story plugins that want +to make use of it. + + +=head1 SEE ALSO + +lastmodified2 + +Blosxom: http://blosxom.sourceforge.net/ + + +=head1 ACKNOWLEDGEMENTS + +storydate is based on Frank Hecker's lastmodified2 plugin, which is +itself based on Bob Schumaker's lastmodified plugin. + +The problem with lastmodified2 is that its HTTP header functionality +requires that it runs very late, which makes it useless for providing +dates to story plugins. storydate is basically just all the parts of +lastmodified2 that can be run early pulled out into a separate plugin. + + +=head1 AUTHOR + +Gavin Carr , http://www.openfusion.net/ + + +=head1 LICENSE + +Copyright 2007, Gavin Carr. + +This plugin is licensed under the same terms as blosxom itself i.e. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +=cut + +# vim:ft=perl:sw=4 + -- 2.30.2