# This code is a part of Slash, and is released under the GPL. # Copyright 1997-2001 by Open Source Development Network. See README # and COPYING for more information, or see http://slashcode.com/. # $Id: RSS.pm,v 1.1.2.4 2001/08/28 15:35:19 jamie Exp $ package Slash::XML::RSS; =head1 NAME Slash::XML::RSS - Perl extension for Slash =head1 SYNOPSIS use Slash::XML; xmlDisplay(%data); =head1 DESCRIPTION LONG DESCRIPTION. =head1 EXPORTED FUNCTIONS =cut use strict; use Slash; use Slash::Utility; use XML::RSS; use base 'Slash::XML'; use vars qw($VERSION); ($VERSION) = ' $Revision: 1.1.2.4 $ ' =~ /\$Revision:\s+([^\s]+)/; #======================================================================== =head2 create(PARAM) Creates RSS. =over 4 =item Parameters =over 4 =item PARAM Hashref of parameters. Currently supported options are below. =over 4 =item version Defaults to "1.0". May be >= "1.0", >= "0.91", or "0.9". =item rdfencoding Defaults to "rdfencoding" in vars. =item title Defaults to "sitename" in vars. =item description Defaults to "slogan" in vars. =item link Defaults to "absolutedir" in vars. =item date Defaults to current date. See date2iso8601(). =item subject Defaults to "rdfsubject" in vars. =item language Defaults to "rdflanguage" in vars. =item creator Defaults to "adminmail" in vars. =item publisher Defaults to "rdfpublisher" in vars. =item rights Defaults to "rdfrights" in vars. =item updatePeriod Defaults to "rdfupdateperiod" in vars. =item updateFrequency Defaults to "rdfupdatefrequency" in vars. =item updateBase Defaults to "rdfupdatebase" in vars. =item image If scalar, then just prints the default image data if scalar is true. If hashref, then may have "title", "url", and "link" passed. =item textinput If scalar, then just prints the default textinput data if scalar is true. If hashref, then may have "title", "description", "name", and "link" passed. =item items An arrayref of hashrefs. If the "story" key of the hashref is true, then the item is passed to rss_story(). Otherwise, "title" and "link" must be defined keys, and any other single-level key may be defined (no multiple level hash keys). =back =back =item Return value The complete RSS data as a string. =back =cut sub create { my($class, $param) = @_; my $self = bless {}, $class; return unless exists $param->{items}; my $constants = getCurrentStatic(); my $version = $param->{version} || '1.0'; my $encoding = $param->{rdfencoding} || $constants->{rdfencoding}; my $rss = XML::RSS->new( version => $version, encoding => $encoding, ); # set defaults my %channel = ( title => $constants->{sitename}, description => $constants->{slogan}, 'link' => $constants->{absolutedir} . '/', # dc date => $self->date2iso8601(), subject => $constants->{rdfsubject}, language => $constants->{rdflanguage}, creator => $constants->{adminmail}, publisher => $constants->{rdfpublisher}, rights => $constants->{rdfrights}, # syn updatePeriod => $constants->{rdfupdateperiod}, updateFrequency => $constants->{rdfupdatefrequency}, updateBase => $constants->{rdfupdatebase}, ); # let $param->{channel} override for (keys %channel) { my $value = defined $param->{channel}{$_} ? $param->{channel}{$_} : $channel{$_}; $channel{$_} = $self->encode($value, $_); } if ($version >= 1.0) { # move from root to proper namespace for (qw(date subject language creator publisher rights)) { $channel{dc}{$_} = delete $channel{$_}; } for (qw(updatePeriod updateFrequency updateBase)) { $channel{syn}{$_} = delete $channel{$_}; } my($item) = @{$param->{items}}; $rss->add_module( prefix => 'slash', uri => 'http://slashcode.com/rss/1.0/modules/Slash/', ) if $item->{story}; } elsif ($version >= 0.91) { # fix mappings for 0.91 $channel{language} = substr($channel{language}, 0, 2); $channel{pubDate} = delete $channel{date}; $channel{managingEditor} = delete $channel{publisher}; $channel{webMaster} = delete $channel{creator}; $channel{copyright} = delete $channel{rights}; } else { # 0.9 for (keys %channel) { delete $channel{$_} unless /^(?:link|title|description)$/; } } # OK, now set it $rss->channel(%channel); # may be boolean if ($param->{image}) { # set defaults my %image = ( title => $constants->{sitename}, url => $constants->{rdfimg}, 'link' => $constants->{absolutedir} . '/', ); # let $param->{image} override if (ref($param->{image}) eq 'HASH') { for (keys %image) { my $value = defined $param->{image}{$_} ? $param->{image}{$_} : $image{$_}; $image{$_} = $self->encode($value, $_); } } # OK, now set it $rss->image(%image); } # may be boolean if ($param->{textinput}) { # set defaults my %textinput = ( title => 'Search ' . $constants->{sitename}, description => 'Search ' . $constants->{sitename} . ' stories', name => 'query', 'link' => $constants->{absolutedir} . '/search.pl', ); # let $param->{textinput} override if (ref($param->{image}) eq 'HASH') { for (keys %textinput) { my $value = defined $param->{textinput}{$_} ? $param->{textinput}{$_} : $textinput{$_}; $textinput{$_} = $self->encode($value, $_); } } # OK, now set it $rss->textinput(%textinput); } my @items; for my $item (@{$param->{items}}) { if ($item->{story} || ( defined($item->{title}) && $item->{title} ne "" && defined($item->{'link'}) && $item->{'link'} ne "" )) { my $encoded_item = {}; # story is hashref to be deleted, containing # story data if ($item->{story}) { # set up story params in $encoded_item ref $self->rss_story($item, $encoded_item, $version); } for my $key (keys %$item) { $encoded_item->{$key} = $self->encode($item->{$key}, $key); } push @items, $encoded_item if keys %$encoded_item; } } # technically, you *must* have items, but that can be # checked by the caller, so we are just gonna return # the incomplete RSS -- pudge # return unless @items; for (@items) { $rss->add_item(%$_); } return $rss->as_string; } #======================================================================== =head2 rss_story(ITEM, ENCODED_ITEM, VERSION) Set up a story item for RSS. Called from create(). =over 4 =item Parameters =over 4 =item ITEM The item hashref passed in the items param key passed to xmlDisplay(). =item ENCODED_ITEM The prepared encoded data from ITEM. =item VERSION The VERSION as defined in create(). Does the Right Thing for >= "1.0", >= "0.91", and "0.9". =back =item Return value The encoded item. =back =cut sub rss_story { my($self, $item, $encoded_item, $version) = @_; # delete it so it won't be processed later my $story = delete $item->{story}; my $constants = getCurrentStatic(); my $slashdb = getCurrentDB(); my $topics = $slashdb->getTopics(); $encoded_item->{title} = $self->encode($story->{title}); $encoded_item->{'link'} = $self->encode("$constants->{absolutedir}/article.pl?sid=$story->{sid}", 'link'); if ($version >= 0.91) { my $desc = $self->rss_item_description($item->{description}); $encoded_item->{description} = $self->encode($desc) if $desc; } if ($version >= 1.0) { my $slashdb = getCurrentDB(); $encoded_item->{dc}{date} = $self->encode($self->date2iso8601($story->{'time'})); $encoded_item->{dc}{subject} = $self->encode($topics->{$story->{tid}}{name}); $encoded_item->{dc}{creator} = $self->encode($slashdb->getUser($story->{uid}, 'nickname')); $encoded_item->{slash}{section} = $self->encode($story->{section}); $encoded_item->{slash}{comments} = $self->encode($story->{commentcount}); $encoded_item->{slash}{hitparade} = $self->encode($story->{hitparade}); $encoded_item->{slash}{department} = $self->encode($story->{dept}) if $constants->{use_dept}; } return $encoded_item; } #======================================================================== =head2 rss_item_description(DESC) Set up an item description. If rdfitemdesc in the vars table is "1", then prints an item's description. If it is some other true value, it will chop the description to that length. If it is false, then no description for the item will be printed. =over 4 =item Parameters =over 4 =item DESC The description. =back =item Return value The fixed description. =back =cut sub rss_item_description { my($self, $desc) = @_; my $constants = getCurrentStatic(); if ($constants->{rdfitemdesc} == 1) { # keep $desc as-is } elsif ($constants->{rdfitemdesc}) { # limit length of $desc $desc = balanceTags(chopEntity($desc, $constants->{rdfitemdesc})); return $desc; } else { undef $desc; } return $desc; } 1; __END__ =head1 SEE ALSO Slash(3), Slash::XML(3). =head1 VERSION $Id: RSS.pm,v 1.1.2.4 2001/08/28 15:35:19 jamie Exp $