diff --git a/docs/gotcha.txt b/docs/gotcha.txt index 7a85c5f8a..66c8047aa 100644 --- a/docs/gotcha.txt +++ b/docs/gotcha.txt @@ -13,6 +13,11 @@ save you many hours of grief. * You must upgrade to WebGUI 7.7.2 before going on to higher versions of WebGUI due to changes in the database table for the Cart. + * The RSSCapable class and RSSFromParent asset have been removed. + Any custom assets using those are recommended to switch to the new + RssFeed AssetAspect. If not used by custom assets, the tables + used by them will be removed from the database. + 7.7.1 -------------------------------------------------------------------- * Keywords are now comma separated rather than space separated. Quotes are diff --git a/docs/upgrades/upgrade_7.7.1-7.7.2.pl b/docs/upgrades/upgrade_7.7.1-7.7.2.pl index c0a227de5..cb9649290 100644 --- a/docs/upgrades/upgrade_7.7.1-7.7.2.pl +++ b/docs/upgrades/upgrade_7.7.1-7.7.2.pl @@ -36,7 +36,7 @@ my $session = start(); # this line required recalculateMatrixListingMedianValue( $session ); addRssFeedAspect($session); addRssFeedAspectToAssets($session); -addRssFeedAspectToCollaboration($session); +convertCollaborationToRssAspect($session); removeRssCapableAsset($session); addCreationTimeToCart($session); addCartKillerActivityToConfig($session); @@ -47,7 +47,7 @@ finish($session); # this line required #---------------------------------------------------------------------------- sub recalculateMatrixListingMedianValue{ my $session = shift; - print "\tRecalculating median value for Matrix Listing ratings... \n" unless $quiet; + print "\tRecalculating median value for Matrix Listing ratings... " unless $quiet; my $matrices = WebGUI::Asset->getRoot($session)->getLineage(['descendants'], { statesToInclude => ['published','trash','clipboard','clipboard-limbo','trash-limbo'], @@ -80,7 +80,7 @@ category = ?",[$medianValue,$listing->{listingId},$category]); sub addRssFeedAspect { my $session = shift; print "\tAdding RssFeed asset aspect..." unless $quiet; - $session->db->write("create table assetAspectRssFeed ( + $session->db->write(q{create table assetAspectRssFeed ( assetId char(22) binary not null, revisionDate bigint not null, itemsPerFeed int(11) default 25, @@ -90,46 +90,73 @@ sub addRssFeedAspect { feedImage char(22) binary, feedImageLink text, feedImageDescription mediumtext, + feedHeaderLinks char(32) default 'rss\natom', primary key (assetId, revisionDate) - )"); + )}); print "Done.\n" unless $quiet; } #---------------------------------------------------------------------------- sub addRssFeedAspectToAssets { my $session = shift; + my $db = $session->db; foreach my $asset_class (qw( WikiMaster SyndicatedContent Gallery GalleryAlbum )) { print "\tAdding RssFeed aspect to $asset_class table..." unless $quiet; - my $db = $session->db; my $pages = $db->read("select assetId,revisionDate from $asset_class"); while (my ($id, $rev) = $pages->array) { - $db->write("insert into assetAspectRssFeed (assetId, revisionDate, itemsPerFeed, feedTitle, feedDescription, feedImage, feedImageLink, feedImageDescription) values (?,?,25,'','',NULL,'','')",[$id,$rev]); + $db->write("INSERT INTO assetAspectRssFeed (assetId, revisionDate, itemsPerFeed, feedTitle, feedDescription, feedImage, feedImageLink, feedImageDescription) VALUES (?,?,25,'','',NULL,'','')",[$id,$rev]); } print "Done.\n" unless $quiet; } } #---------------------------------------------------------------------------- -sub addRssFeedAspectToCollaboration { +sub convertCollaborationToRssAspect { my $session = shift; print "\tAdding RssFeed aspect to Collaboration, (porting rssCapableRssLimit to itemsPerFeed)..." unless $quiet; my $db = $session->db; - my $pages = $db->read("select assetId,revisionDate,rssCapableRssLimit from RSSCapable"); - while (my ($id, $rev, $limit) = $pages->array) { - $db->write("insert into assetAspectRssFeed (assetId, revisionDate, itemsPerFeed, feedTitle, feedDescription, feedImage, feedImageLink, feedImageDescription) values (?,?,?,'','',NULL,'','')",[$id,$rev,$limit || 25]); + my @rssFromParents; + my $pages = $db->read("SELECT Collaboration.assetId, Collaboration.revisionDate, RSSCapable.rssCapableRssLimit, RSSCapable.rssCapableRssFromParentId, RSSCapable.rssCapableRssEnabled FROM Collaboration INNER JOIN RSSCapable ON Collaboration.assetId=RSSCapable.assetId AND Collaboration.revisionDate=RSSCapable.revisionDate"); + while (my ($id, $rev, $limit, $fromParent, $enabled) = $pages->array) { + if ($fromParent) { + push @rssFromParents, $fromParent; + } + my $headerLinks = $enabled ? "rss\natom" : q{}; + $db->write("INSERT INTO assetAspectRssFeed (assetId, revisionDate, itemsPerFeed, feedTitle, feedDescription, feedImage, feedImageLink, feedImageDescription, feedHeaderLinks) VALUES (?,?,?,'','',NULL,'','',?)",[$id,$rev,$limit || 25, $headerLinks]); } + for my $assetId (@rssFromParents) { + my $asset = WebGUI::Asset->newPending($session, $assetId); + $asset->purge; + } + $db->write("DELETE FROM RSSCapable WHERE assetId IN (SELECT assetId FROM Collaboration GROUP BY assetId)"); print "Done.\n" unless $quiet; } #---------------------------------------------------------------------------- sub removeRssCapableAsset { my $session = shift; - print "\tRemoving prior RssCapable asset..." unless $quiet; - $session->db->write("drop table RSSCapable"); - $session->db->write("drop table RSSFromParent"); - unlink ( $webguiRoot . '/lib/WebGUI/Asset/RSSCapable.pm' ); - unlink ( $webguiRoot . '/lib/WebGUI/Asset/RSSFromParent.pm' ); - print "Done.\n" unless $quiet; + print "\tChecking for uses of RSSCapable...\n" unless $quiet; + my @rssCapableClasses = $session->db->buildArray('SELECT className FROM RSSCapable INNER JOIN asset ON RSSCapable.assetId=asset.assetId GROUP BY className'); + if (@rssCapableClasses) { + warn "\t\tThis site is using the assets\n\t\t\t" . join(', ', @rssCapableClasses) . "\n\t\twhich use the RSSCapable class! Support RSSCapable has been dropped and it will no longer be maintained.\n"; + } + else { + print "\t\tNot used, removing.\n" unless $quiet; + $session->db->write("DROP TABLE RSSCapable"); + $session->db->write("DROP TABLE RSSFromParent"); + my $rssCapableTemplates = WebGUI::Asset->getRoot($session)->getLineage(['descendants'], { + statesToInclude => [qw(published clipboard clipboard-limbo trash-limbo)], + statusToInclude => [qw(approved pending archived)], + returnObjects => 1, + includeOnlyClasses => ['WebGUI::Asset::Template'], + joinClass => 'WebGUI::Asset::Template', + whereClause => q{template.namespace = 'RSSCapable/RSS'}, + }); + for my $template (@{$rssCapableTemplates}) { + $template->trash; + } + } + print "\tDone.\n" unless $quiet; } #---------------------------------------------------------------------------- diff --git a/lib/WebGUI/Asset.pm b/lib/WebGUI/Asset.pm index 8cd70a616..7b031cfce 100644 --- a/lib/WebGUI/Asset.pm +++ b/lib/WebGUI/Asset.pm @@ -2340,9 +2340,9 @@ sub update { # next unless (exists $properties->{$property} || exists $definition->{properties}{$property}{defaultValue}); # skip a property unless it was specified to be set by the properties field next unless (exists $properties->{$property}); - + my $propertyDefinition = $definition->{property}{$property}; # skip a property if it has the display only flag set - next if ($definition->{properties}{$property}{displayOnly}); + next if ($propertyDefinition->{displayOnly}); # skip properties that aren't yet in the table if (!exists $tableFields{$property}) { @@ -2358,14 +2358,16 @@ sub update { } # apply filter logic on a property to validate or fix it's value - if (exists $definition->{properties}{$property}{filter}) { - my $filter = $definition->{properties}{$property}{filter}; - $value = $self->$filter($value, $property); - } + if (exists $propertyDefinition->{filter}) { + my $filter = $propertyDefinition->{filter}; + $value = $self->$filter($value, $property); + } - # use the default value because default and update were both undef - if ($value eq "" && exists $definition->{properties}{$property}{defaultValue}) { - $value = $definition->{properties}{$property}{defaultValue}; + # if the value is undefined, use the default if possible + # unless allowEmpty has been set, do this for empty strings as well + if ( ( !defined $value || ( $value eq q{} && ! $propertyDefinition->{allowEmpty} ) ) + && exists $propertyDefinition->{defaultValue} ) { + $value = $propertyDefinition->{defaultValue}; if (ref($value) eq 'ARRAY') { $value = $value->[0]; } diff --git a/lib/WebGUI/Asset/Wobject/Collaboration.pm b/lib/WebGUI/Asset/Wobject/Collaboration.pm index 5275e27fd..f971739b8 100644 --- a/lib/WebGUI/Asset/Wobject/Collaboration.pm +++ b/lib/WebGUI/Asset/Wobject/Collaboration.pm @@ -62,16 +62,6 @@ sub _visitorCacheOk { && !$self->session->form->process('sortBy')); } -#------------------------------------------------------------------- -# encode a string to include in xml (for RSS export) -sub _xml_encode { - my $text = shift; - $text =~ s/&/&/g; - $text =~ s//\]\]>/g; - return $text; -} - #------------------------------------------------------------------- sub addChild { my $self = shift; @@ -1174,7 +1164,6 @@ sub prepareView { my $self = shift; $self->next::method; my $template = WebGUI::Asset::Template->new($self->session, $self->get("collaborationTemplateId")) or die "no good: ".$self->get("collaborationTemplateId"); - $self->session->style->setLink($self->getRssFeedUrl,{ rel=>'alternate', type=>'application/rss+xml', title=>$self->get('title') . ' RSS' }); $template->prepare($self->getMetaDataAsTemplateVariables); $self->{_viewTemplate} = $template; } diff --git a/lib/WebGUI/Asset/Wobject/SyndicatedContent.pm b/lib/WebGUI/Asset/Wobject/SyndicatedContent.pm index 59a1e8dcb..ddb7d7b02 100644 --- a/lib/WebGUI/Asset/Wobject/SyndicatedContent.pm +++ b/lib/WebGUI/Asset/Wobject/SyndicatedContent.pm @@ -308,11 +308,6 @@ sub prepareView { my $template = WebGUI::Asset::Template->new($self->session, $self->get("templateId")); $template->prepare($self->getMetaDataAsTemplateVariables); $self->{_viewTemplate} = $template; - my $title = $self->get("title"); - my $style = $self->session->style; - $style->setLink($self->getUrl("func=viewRss"), { rel=>'alternate', type=>'application/rss+xml', title=>$title.' (RSS)' }); - $style->setLink($self->getUrl("func=viewRdf"), { rel=>'alternate', type=>'application/rdf+xml', title=>$title.' (RDF)' }); - $style->setLink($self->getUrl("func=viewAtom"), { rel=>'alternate', type=>'application/atom+xml', title=>$title.' (Atom)' }); } @@ -408,6 +403,20 @@ sub www_viewRSS10 { return $self->www_viewRdf; } +#------------------------------------------------------------------- + +=head2 www_viewRSS ( ) + +Deprecated. Use www_viewRss() instead. + +=cut + +sub www_viewRSS { + my $self = shift; + return $self->www_viewRss; +} + + #------------------------------------------------------------------- =head2 www_viewRSS20 ( ) diff --git a/lib/WebGUI/AssetAspect/RssFeed.pm b/lib/WebGUI/AssetAspect/RssFeed.pm index b8d638468..21dd73a36 100644 --- a/lib/WebGUI/AssetAspect/RssFeed.pm +++ b/lib/WebGUI/AssetAspect/RssFeed.pm @@ -113,6 +113,23 @@ sub definition { label => $i18n->get('feedImageDescription'), hoverHelp => $i18n->get('feedImageDescription hoverHelp') }, + feedHeaderLinks => { + fieldType => "checkList", + defaultValue => "rss\natom", + tab => "rss", + options => do { + my %headerLinksOptions; + tie %headerLinksOptions, 'Tie::IxHash'; + %headerLinksOptions = ( + rss => $i18n->get('rssLinkOption'), + atom => $i18n->get('atomLinkOption'), + rdf => $i18n->get('rdfLinkOption'), + ); + \%headerLinksOptions; + }, + label => $i18n->get('feedHeaderLinks'), + hoverHelp => $i18n->get('feedHeaderLinks hoverHelp') + }, ); push(@{$definition}, { autoGenerateForms => 1, @@ -261,6 +278,18 @@ sub getAtomFeedUrl { #------------------------------------------------------------------- +=head2 getRdfFeedUrl () + +Returns $self->getUrl('func=viewRdf'). + +=cut + +sub getRdfFeedUrl { + shift->getUrl("func=viewRdf"); +} + +#------------------------------------------------------------------- + =head2 getRssFeedUrl () Returns $self->getUrl('func=viewRss'). @@ -280,7 +309,33 @@ Returns the current asset's URL with .atom concatenated onto it. =cut sub getStaticAtomFeedUrl { - shift->getUrl() . '.atom'; + my $self = shift; + my $url = $self->get("url") . '.atom'; + $url = $self->session->url->gateway($url); + if ($self->get("encryptPage")) { + $url = $self->session->url->getSiteURL . $url; + $url =~ s/^http:/https:/; + } + return $url; +} + +#------------------------------------------------------------------- + +=head2 getStaticRdfFeedUrl () + +Returns the current asset's URL with .rdf concatenated onto it. + +=cut + +sub getStaticRdfFeedUrl { + my $self = shift; + my $url = $self->get("url") . '.rdf'; + $url = $self->session->url->gateway($url); + if ($self->get("encryptPage")) { + $url = $self->session->url->getSiteURL . $url; + $url =~ s/^http:/https:/; + } + return $url; } #------------------------------------------------------------------- @@ -292,7 +347,14 @@ Returns the current asset's URL with .rss concatenated onto it. =cut sub getStaticRssFeedUrl { - shift->getUrl() . '.rss'; + my $self = shift; + my $url = $self->get("url") . '.rss'; + $url = $self->session->url->gateway($url); + if ($self->get("encryptPage")) { + $url = $self->session->url->getSiteURL . $url; + $url =~ s/^http:/https:/; + } + return $url; } #------------------------------------------------------------------- @@ -342,6 +404,41 @@ sub getFeed { return $feed; } +sub prepareView { + my $self = shift; + $self->addHeaderLinks; + return $self->next::method(@_); +} + +sub addHeaderLinks { + my $self = shift; + my $style = $self->session->style; + my $title = $self->get('feedTitle') || $self->get("title"); + my %feeds = map { $_ => 1 } split /\n/, $self->get('feedHeaderLinks'); + my $addType = keys %feeds > 1; + if ($feeds{rss}) { + $style->setLink($self->getRssFeedUrl, { + rel => 'alternate', + type => 'application/rss+xml', + title => $title . ( $addType ? ' (RSS)' : ''), + }); + } + if ($feeds{atom}) { + $style->setLink($self->getAtomFeedUrl, { + rel => 'alternate', + type => 'application/atom+xml', + title => $title . ( $addType ? ' (Atom)' : ''), + }); + } + if ($feeds{rdf}) { + $style->setLink($self->getRdfFeedUrl, { + rel => 'alternate', + type => 'application/rdf+xml', + title => $title . ( $addType ? ' (RDF)' : ''), + }); + } +} + #------------------------------------------------------------------- =head2 www_viewAtom () diff --git a/lib/WebGUI/i18n/English/AssetAspect_RssFeed.pm b/lib/WebGUI/i18n/English/AssetAspect_RssFeed.pm index 9e71c4d8b..aaa08724c 100644 --- a/lib/WebGUI/i18n/English/AssetAspect_RssFeed.pm +++ b/lib/WebGUI/i18n/English/AssetAspect_RssFeed.pm @@ -92,8 +92,23 @@ our $I18N = { lastUpdated => 1236820473, context => q|The title of the RSS tab on the asset's edit form.| }, - + + 'feedHeaderLinks' => { + message => q|HTML Header Feed Links|, + }, + 'feedHeaderLinks hoverHelp' => { + message => q|Select which feed types to include in the HTML headers, which many browsers will offer as options to users.|, + }, + 'rssLinkOption' => { + message => q|RSS 2.0|, + }, + 'atomLinkOption' => { + message => 'Atom', + }, + 'rdfLinkOption' => { + message => 'RDF/RSS 1.0', + }, }; 1; -#vim:ft=perl \ No newline at end of file +#vim:ft=perl