Add storydate.
authorGavin Carr <gonzai@users.sourceforge.net>
Thu, 27 Sep 2007 23:11:11 +0000 (23:11 +0000)
committerGavin Carr <gonzai@users.sourceforge.net>
Thu, 27 Sep 2007 23:11:11 +0000 (23:11 +0000)
gavinc/storydate [new file with mode: 0644]

diff --git a/gavinc/storydate b/gavinc/storydate
new file mode 100644 (file)
index 0000000..0341ea0
--- /dev/null
@@ -0,0 +1,279 @@
+# Blosxom Plugin: storydate
+# Author(s): Gavin Carr <gavin@openfusion.com.au>
+# (based on work by Frank Hecker <hecker@hecker.org>
+#  and Bob Schumaker <cobblers@pobox.com>)
+# 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<strftime(3)> 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<strftime(3)> 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 <gavin@openfusion.com.au>, 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
+