Merge branch 'master' of git://github.com/pdonelan/webgui into filepump
This commit is contained in:
commit
8e3891a7bd
44 changed files with 5516 additions and 80 deletions
|
|
@ -17,6 +17,7 @@ package WebGUI::Asset;
|
|||
use Carp qw( croak confess );
|
||||
use Scalar::Util qw( blessed );
|
||||
use Clone qw(clone);
|
||||
use JSON;
|
||||
|
||||
use WebGUI::AssetBranch;
|
||||
use WebGUI::AssetClipboard;
|
||||
|
|
@ -1927,8 +1928,9 @@ sub outputWidgetMarkup {
|
|||
my $styleTemplateId = shift;
|
||||
|
||||
# construct / retrieve the values we'll use later.
|
||||
my $assetId = $self->getId;
|
||||
my $session = $self->session;
|
||||
my $assetId = $self->getId;
|
||||
my $hexId = $session->id->toHex($assetId);
|
||||
my $conf = $session->config;
|
||||
my $extras = $conf->get('extrasURL');
|
||||
|
||||
|
|
@ -1952,8 +1954,10 @@ sub outputWidgetMarkup {
|
|||
$content = $self->session->style->process($content,$styleTemplateId);
|
||||
}
|
||||
WebGUI::Macro::process($session, \$content);
|
||||
$session->log->warn($content);
|
||||
my ($headTags, $body) = WebGUI::HTML::splitHeadBody($content);
|
||||
my $jsonContent = to_json( { "asset$assetId" => { content => $body } } );
|
||||
$body = $content;
|
||||
my $jsonContent = to_json( { "asset$hexId" => { content => $body } } );
|
||||
$storage->addFileFromScalar("$assetId.js", "data = $jsonContent");
|
||||
my $jsonUrl = $storage->getUrl("$assetId.js");
|
||||
|
||||
|
|
@ -1979,15 +1983,15 @@ sub outputWidgetMarkup {
|
|||
<script type='text/javascript' src='$wgWidgetJs'></script>
|
||||
<script type='text/javascript'>
|
||||
function setupPage() {
|
||||
WebGUI.widgetBox.doTemplate('widget$assetId'); WebGUI.widgetBox.retargetLinksAndForms();
|
||||
WebGUI.widgetBox.doTemplate('widget$hexId'); WebGUI.widgetBox.retargetLinksAndForms();
|
||||
WebGUI.widgetBox.initButton( { 'wgWidgetPath' : '$wgWidgetPath', 'fullUrl' : '$fullUrl', 'assetId' : '$assetId', 'width' : $width, 'height' : $height, 'templateId' : '$templateId' } );
|
||||
}
|
||||
YAHOO.util.Event.addListener(window, 'load', setupPage);
|
||||
</script>
|
||||
$headTags
|
||||
</head>
|
||||
<body id="widget$assetId">
|
||||
\${asset$assetId.content}
|
||||
<body id="widget$hexId">
|
||||
\${asset$hexId.content}
|
||||
</body>
|
||||
</html>
|
||||
OUTPUT
|
||||
|
|
|
|||
900
lib/WebGUI/Asset/Story.pm
Normal file
900
lib/WebGUI/Asset/Story.pm
Normal file
|
|
@ -0,0 +1,900 @@
|
|||
package WebGUI::Asset::Story;
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2009 Plain Black Corporation.
|
||||
-------------------------------------------------------------------
|
||||
Please read the legal notices (docs/legal.txt) and the license
|
||||
(docs/license.txt) that came with this distribution before using
|
||||
this software.
|
||||
-------------------------------------------------------------------
|
||||
http://www.plainblack.com info@plainblack.com
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Class::C3;
|
||||
use base 'WebGUI::Asset';
|
||||
use Tie::IxHash;
|
||||
use WebGUI::Utility;
|
||||
use WebGUI::International;
|
||||
use JSON qw/from_json to_json/;
|
||||
use Storable qw/dclone/;
|
||||
use Data::Dumper;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Asset::Story
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The Story Asset is like a Thread for the Collaboration.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use WebGUI::Asset::Story;
|
||||
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
These methods are available from this class:
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 addChild ( )
|
||||
|
||||
You can't add children to a Story.
|
||||
|
||||
=cut
|
||||
|
||||
sub addChild {
|
||||
return undef;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 addRevision
|
||||
|
||||
Copy storage locations so that purging individual revisions works correctly.
|
||||
|
||||
Request autocommit.
|
||||
|
||||
=cut
|
||||
|
||||
sub addRevision {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $newSelf = $self->next::method(@_);
|
||||
|
||||
my $newProperties = {
|
||||
isHidden => 1,
|
||||
};
|
||||
|
||||
$newSelf->update($newProperties);
|
||||
|
||||
my $newPhotoData = $newSelf->duplicatePhotoData;
|
||||
$newSelf->setPhotoData($newPhotoData);
|
||||
$newSelf->requestAutoCommit;
|
||||
|
||||
return $newSelf;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( session, definition )
|
||||
|
||||
defines asset properties for New Asset instances. You absolutely need
|
||||
this method in your new Assets.
|
||||
|
||||
=head3 session
|
||||
|
||||
=head3 definition
|
||||
|
||||
A hash reference passed in from a subclass definition.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my %properties;
|
||||
tie %properties, 'Tie::IxHash';
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Story');
|
||||
%properties = (
|
||||
headline => {
|
||||
fieldType => 'text',
|
||||
#label => $i18n->get('headline'),
|
||||
#hoverHelp => $i18n->get('headline help'),
|
||||
defaultValue => '',
|
||||
},
|
||||
subtitle => {
|
||||
fieldType => 'textarea',
|
||||
#label => $i18n->get('subtitle'),
|
||||
#hoverHelp => $i18n->get('subtitle help'),
|
||||
defaultValue => '',
|
||||
},
|
||||
byline => {
|
||||
fieldType => 'text',
|
||||
#label => $i18n->get('byline'),
|
||||
#hoverHelp => $i18n->get('byline help'),
|
||||
defaultValue => '',
|
||||
},
|
||||
location => {
|
||||
fieldType => 'text',
|
||||
#label => $i18n->get('location'),
|
||||
#hoverHelp => $i18n->get('location help'),
|
||||
defaultValue => '',
|
||||
},
|
||||
highlights => {
|
||||
fieldType => 'textarea',
|
||||
#label => $i18n->get('highlights'),
|
||||
#hoverHelp => $i18n->get('highlights help'),
|
||||
defaultValue => '',
|
||||
},
|
||||
story => {
|
||||
fieldType => 'HTMLArea',
|
||||
#label => $i18n->get('highlights'),
|
||||
#hoverHelp => $i18n->get('highlights help'),
|
||||
#richEditId => $self->parent->getStoryRichEdit,
|
||||
defaultValue => '',
|
||||
},
|
||||
photo => {
|
||||
fieldType => 'text',
|
||||
defaultValue => '[]',
|
||||
noFormPost => 1,
|
||||
},
|
||||
);
|
||||
push(@{$definition}, {
|
||||
assetName => $i18n->get('assetName'),
|
||||
icon => 'assets.gif',
|
||||
tableName => 'Story',
|
||||
className => 'WebGUI::Asset::Story',
|
||||
properties => \%properties,
|
||||
autoGenerateForms => 0,
|
||||
});
|
||||
return $class->next::method($session, $definition);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 duplicate ( )
|
||||
|
||||
Extent the method from Asset to handle duplicating storage locations.
|
||||
|
||||
=cut
|
||||
|
||||
sub duplicate {
|
||||
my $self = shift;
|
||||
my $newSelf = $self->next::method(@_);
|
||||
my $newPhotoData = $newSelf->duplicatePhotoData;
|
||||
$newSelf->setPhotoData($newPhotoData);
|
||||
return $newSelf;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 duplicatePhotoData ( )
|
||||
|
||||
Duplicate photo data, particularly storage locations. Returns the duplicated
|
||||
perl structure.
|
||||
|
||||
=cut
|
||||
|
||||
sub duplicatePhotoData {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $photoData = $self->getPhotoData;
|
||||
PHOTO: foreach my $photo (@{ $photoData }) {
|
||||
next PHOTO unless $photo->{storageId};
|
||||
my $oldStorage = WebGUI::Storage->get($session, $photo->{storageId});
|
||||
my $newStorage = $oldStorage->copy;
|
||||
$photo->{storageId} = $newStorage->getId;
|
||||
}
|
||||
return $photoData;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 exportAssetData ( )
|
||||
|
||||
See WebGUI::AssetPackage::exportAssetData() for details.
|
||||
Adds all storage locations to the package data.
|
||||
|
||||
=cut
|
||||
|
||||
sub exportAssetData {
|
||||
my $self = shift;
|
||||
my $exportData = $self->next::method;
|
||||
PHOTO: foreach my $photo (@{ $self->getPhotoData }) {
|
||||
next PHOTO unless $photo->{storageId};
|
||||
push @{ $exportData->{storage} }, $photo->{storageId};
|
||||
}
|
||||
return $exportData;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 formatDuration ( $lastUpdated )
|
||||
|
||||
Format the time since this story was last updated. If it is longer than 1 week, then
|
||||
return the date.
|
||||
|
||||
=head3 $lastUpdated
|
||||
|
||||
The date this was last updated. If left blank, it uses the revisionDate.
|
||||
|
||||
=cut
|
||||
|
||||
sub formatDuration {
|
||||
my ($self, $lastUpdated) = @_;
|
||||
$lastUpdated = defined $lastUpdated ? $lastUpdated : $self->get('revisionDate');
|
||||
my $session = $self->session;
|
||||
my $datetime = $session->datetime;
|
||||
my $duration = time() - $lastUpdated;
|
||||
if ($duration > 86400) { ##1 day
|
||||
return join ' ', $datetime->secondsToInterval($duration);
|
||||
}
|
||||
else {
|
||||
my $formattedDuration = '';
|
||||
my $hours = int($duration/3600) * 3600;
|
||||
my @hours = $datetime->secondsToInterval($hours);
|
||||
if ($hours[0]) {
|
||||
$formattedDuration = join ' ', @hours;
|
||||
}
|
||||
my $minutes = round(($duration - $hours)/60)*60;
|
||||
my @minutes = $datetime->secondsToInterval($minutes);
|
||||
if ($minutes[0]) {
|
||||
$formattedDuration .= ', ', if $formattedDuration;
|
||||
$formattedDuration .= join ' ', @minutes;
|
||||
}
|
||||
return $formattedDuration;
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getArchive ( )
|
||||
|
||||
Returns the parent archive for this Story. Cache the entry for speed.
|
||||
|
||||
=cut
|
||||
|
||||
sub getArchive {
|
||||
my $self = shift;
|
||||
if (!$self->{_archive}) {
|
||||
$self->{_archive} = $self->getParent->getParent;
|
||||
}
|
||||
return $self->{_archive};
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAutoCommitWorkflowId ( )
|
||||
|
||||
Get the autocommit workflow from the archive containing this Story and
|
||||
use it.
|
||||
|
||||
=cut
|
||||
|
||||
sub getAutoCommitWorkflowId {
|
||||
my $self = shift;
|
||||
my $archive = $self->getArchive;
|
||||
if ($archive->hasBeenCommitted) {
|
||||
return $archive->get('approvalWorkflowId')
|
||||
|| $self->session->setting->get('defaultVersionTagWorkflow');
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getCrumbTrail ( )
|
||||
|
||||
Returns the crumb trail for this Story. If rendered from inside
|
||||
a Topic, it will insert the Topic information into the crumb trail.
|
||||
|
||||
The crumb trail will be a loop of variables, in order from this Story's
|
||||
StoryArchive, the topic, if present, and then this story.
|
||||
|
||||
=cut
|
||||
|
||||
sub getCrumbTrail {
|
||||
my $self = shift;
|
||||
my $crumb_loop = [];
|
||||
my $archive = $self->getArchive;
|
||||
push @{ $crumb_loop }, {
|
||||
title => $archive->getTitle,
|
||||
url => $archive->getUrl,
|
||||
};
|
||||
my $topic = $self->topic;
|
||||
if ($topic) {
|
||||
push @{ $crumb_loop }, {
|
||||
title => $topic->getTitle,
|
||||
url => $topic->getUrl,
|
||||
};
|
||||
}
|
||||
push @{ $crumb_loop }, {
|
||||
title => $self->getTitle,
|
||||
url => $self->getUrl,
|
||||
};
|
||||
return $crumb_loop;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getEditForm ( )
|
||||
|
||||
Returns a templated form for adding or editing Stories.
|
||||
|
||||
=cut
|
||||
|
||||
sub getEditForm {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Story');
|
||||
my $form = $session->form;
|
||||
my $archive = $self->getArchive;
|
||||
my $isNew = $self->getId eq 'new';
|
||||
my $url = $isNew ? $archive->getUrl : $self->getUrl;
|
||||
my $title = $self->getTitle;
|
||||
my $var = {
|
||||
formHeader => WebGUI::Form::formHeader($session, {action => $url})
|
||||
. WebGUI::Form::hidden($session, { name => 'func', value => 'editSave' })
|
||||
. WebGUI::Form::hidden($session, { name => 'proceed', value => 'showConfirmation' })
|
||||
,
|
||||
formFooter => WebGUI::Form::formFooter($session),
|
||||
formTitle => $isNew
|
||||
? $i18n->get('add a story','Asset_StoryArchive')
|
||||
: $i18n->get('editing','Asset_WikiPage').' '.$title,
|
||||
headlineForm => WebGUI::Form::text($session, {
|
||||
name => 'headline',
|
||||
value => $form->get('headline') || $self->get('headline'),
|
||||
} ),
|
||||
titleForm => WebGUI::Form::text($session, {
|
||||
name => 'title',
|
||||
value => $form->get('title') || $self->get('title'),
|
||||
} ),
|
||||
subtitleForm => WebGUI::Form::textarea($session, {
|
||||
name => 'subtitle',
|
||||
value => $form->get('subtitle') || $self->get('subtitle')
|
||||
} ),
|
||||
bylineForm => WebGUI::Form::text($session, {
|
||||
name => 'byline',
|
||||
value => $form->get('byline') || $self->get('byline')
|
||||
} ),
|
||||
locationForm => WebGUI::Form::text($session, {
|
||||
name => 'location',
|
||||
value => $form->get('location') || $self->get('location')
|
||||
} ),
|
||||
keywordsForm => WebGUI::Form::keywords($session, {
|
||||
name => 'keywords',
|
||||
value => $form->get('keywords') || WebGUI::Keyword->new($session)->getKeywordsForAsset({ asset => $self })
|
||||
} ),
|
||||
highlightsForm => WebGUI::Form::textarea($session, {
|
||||
name => 'highlights',
|
||||
value => $form->get('highlights') || $self->get('highlights')
|
||||
} ),
|
||||
storyForm => WebGUI::Form::HTMLArea($session, {
|
||||
name => 'story',
|
||||
value => $form->get('story') || $self->get('story'),
|
||||
richEditId => $archive->get('richEditorId')
|
||||
}),
|
||||
saveButton => WebGUI::Form::submit($session, {
|
||||
name => 'saveStory',
|
||||
value => $i18n->get('save story'),
|
||||
}),
|
||||
cancelButton => WebGUI::Form::button($session, {
|
||||
name => 'cancel',
|
||||
value => $i18n->get('cancel','WebGUI'),
|
||||
extras => q|onclick="history.go(-1);" class="backwardButton"|,
|
||||
}),
|
||||
saveAndAddButton => WebGUI::Form::submit($session, {
|
||||
name => 'saveAndReturn',
|
||||
value => $i18n->get('save and add another photo'),
|
||||
}),
|
||||
};
|
||||
$var->{ photo_form_loop } = [];
|
||||
##Provide forms for the existing photos, if any
|
||||
##Existing photos get a delete Yes/No.
|
||||
##And a form for new ones
|
||||
my $photoData = $self->getPhotoData;
|
||||
my $numberOfPhotos = scalar @{ $photoData };
|
||||
foreach my $photoIndex (1..$numberOfPhotos) {
|
||||
my $photo = $photoData->[$photoIndex-1];
|
||||
push @{ $var->{ photo_form_loop } }, {
|
||||
imgUploadForm => WebGUI::Form::image($session, {
|
||||
name => 'photo'.$photoIndex,
|
||||
maxAttachments => 1,
|
||||
value => $photo->{storageId},
|
||||
}),
|
||||
imgCaptionForm => WebGUI::Form::text($session, {
|
||||
name => 'imgCaption'.$photoIndex,
|
||||
value => $photo->{caption},
|
||||
}),
|
||||
imgByLineForm => WebGUI::Form::text($session, {
|
||||
name => 'imgByline'.$photoIndex,
|
||||
value => $photo->{byLine},
|
||||
}),
|
||||
imgAltForm => WebGUI::Form::text($session, {
|
||||
name => 'imgAlt'.$photoIndex,
|
||||
value => $photo->{alt},
|
||||
}),
|
||||
imgTitleForm => WebGUI::Form::text($session, {
|
||||
name => 'imgTitle'.$photoIndex,
|
||||
value => $photo->{title},
|
||||
}),
|
||||
imgUrlForm => WebGUI::Form::url($session, {
|
||||
name => 'imgUrl'.$photoIndex,
|
||||
value => $photo->{url},
|
||||
}),
|
||||
imgDeleteForm => WebGUI::Form::yesNo($session, {
|
||||
name => 'deletePhoto'.$photoIndex,
|
||||
value => 0,
|
||||
}),
|
||||
};
|
||||
}
|
||||
push @{ $var->{ photo_form_loop } }, {
|
||||
imgUploadForm => WebGUI::Form::image($session, {
|
||||
name => 'newPhoto',
|
||||
maxAttachments => 1,
|
||||
}),
|
||||
imgCaptionForm => WebGUI::Form::text($session, {
|
||||
name => 'newImgCaption',
|
||||
}),
|
||||
imgByLineForm => WebGUI::Form::text($session, {
|
||||
name => 'newImgByline',
|
||||
}),
|
||||
imgAltForm => WebGUI::Form::text($session, {
|
||||
name => 'newImgAlt',
|
||||
}),
|
||||
imgTitleForm => WebGUI::Form::text($session, {
|
||||
name => 'newImgTitle',
|
||||
}),
|
||||
imgUrlForm => WebGUI::Form::url($session, {
|
||||
name => 'newImgUrl',
|
||||
}),
|
||||
};
|
||||
if ($isNew) {
|
||||
$var->{formHeader} .= WebGUI::Form::hidden($session, { name => 'assetId', value => 'new' })
|
||||
. WebGUI::Form::hidden($session, { name => 'class', value => $form->process('class', 'className') });
|
||||
}
|
||||
else {
|
||||
$var->{formHeader} .= WebGUI::Form::hidden($session, { name => 'url', value => $url});
|
||||
}
|
||||
return $self->processTemplate($var, $archive->get('editStoryTemplateId'));
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getPhotoData ( )
|
||||
|
||||
Returns the photo hash formatted as perl data. See also L<setPhotoData>.
|
||||
|
||||
=cut
|
||||
|
||||
sub getPhotoData {
|
||||
my $self = shift;
|
||||
if (!exists $self->{_photoData}) {
|
||||
my $json = $self->get('photo');
|
||||
$json ||= '[]';
|
||||
$self->{_photoData} = from_json($json);
|
||||
}
|
||||
return dclone($self->{_photoData});
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getRssData ( )
|
||||
|
||||
Returns RSS data for this Story. The date of the RSS item is the lastModified
|
||||
property of the Asset.
|
||||
|
||||
=cut
|
||||
|
||||
sub getRssData {
|
||||
my $self = shift;
|
||||
my $data = {
|
||||
title => $self->get('headline') || $self->getTitle,
|
||||
description => $self->get('subtitle'),
|
||||
'link' => $self->getUrl,
|
||||
author => $self->get('byline'),
|
||||
date => $self->get('lastModified'),
|
||||
};
|
||||
return $data;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 prepareView ( )
|
||||
|
||||
Extent the default method to handle the case when a Story Topic is rendering
|
||||
this Story.
|
||||
|
||||
=cut
|
||||
|
||||
sub prepareView {
|
||||
my $self = shift;
|
||||
$self->next::method();
|
||||
my $templateId;
|
||||
my $topic = $self->topic;
|
||||
if ($topic) {
|
||||
$templateId = $topic->get('storyTemplateId');
|
||||
}
|
||||
else {
|
||||
$templateId = $self->getArchive->get('storyTemplateId');
|
||||
}
|
||||
my $template = WebGUI::Asset::Template->new($self->session, $templateId);
|
||||
$template->prepare;
|
||||
$self->{_viewTemplate} = $template;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 processPropertiesFromFormPost ( )
|
||||
|
||||
Handle photos and photo metadata, like captions, etc.
|
||||
|
||||
=cut
|
||||
|
||||
sub processPropertiesFromFormPost {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
$self->next::method;
|
||||
my $form = $session->form;
|
||||
##Handle old data first, to avoid iterating across a newly added photo.
|
||||
my $photoData = $self->getPhotoData;
|
||||
my $numberOfPhotos = scalar @{ $photoData };
|
||||
##Post process photo data here.
|
||||
PHOTO: foreach my $photoIndex (1..$numberOfPhotos) {
|
||||
##TODO: Deletion check and storage cleanup
|
||||
my $storageId = $photoData->[$photoIndex-1]->{storageId};
|
||||
if ($form->process('deletePhoto'.$photoIndex, 'yesNo')) {
|
||||
my $storage = WebGUI::Storage->get($session, $storageId);
|
||||
$storage->delete if $storage;
|
||||
splice @{ $photoData }, $photoIndex-1, 1;
|
||||
next PHOTO;
|
||||
}
|
||||
my $newPhoto = {
|
||||
storageId => $form->process('photo' .$photoIndex, 'image', $storageId),
|
||||
caption => $form->process('imgCaption'.$photoIndex, 'text'),
|
||||
alt => $form->process('imgAlt' .$photoIndex, 'text'),
|
||||
title => $form->process('imgTitle' .$photoIndex, 'text'),
|
||||
byLine => $form->process('imgByline' .$photoIndex, 'text'),
|
||||
url => $form->process('imgUrl' .$photoIndex, 'url' ),
|
||||
};
|
||||
splice @{ $photoData }, $photoIndex-1, 1, $newPhoto;
|
||||
}
|
||||
my $newStorage = $form->process('newPhoto', 'image');
|
||||
if ($newStorage) {
|
||||
push @{ $photoData }, {
|
||||
caption => $form->process('newImgCaption', 'text'),
|
||||
alt => $form->process('newImgAlt', 'text'),
|
||||
title => $form->process('newImgTitle', 'text'),
|
||||
byLine => $form->process('newImgByline', 'text'),
|
||||
url => $form->process('newImgUrl', 'url'),
|
||||
storageId => $newStorage,
|
||||
};
|
||||
}
|
||||
$self->setPhotoData($photoData);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 purge ( )
|
||||
|
||||
Cleaning up all storage objects in all revisions.
|
||||
|
||||
=cut
|
||||
|
||||
sub purge {
|
||||
my $self = shift;
|
||||
##Delete all storage locations from all revisions of the Asset
|
||||
my $sth = $self->session->db->read("select photo from Story where assetId=?",[$self->getId]);
|
||||
STORAGE: while (my ($json) = $sth->array) {
|
||||
my $photos = from_json($json);
|
||||
PHOTO: foreach my $photo (@{ $photos }) {
|
||||
next PHOTO unless $photo->{storageId};
|
||||
my $storage = WebGUI::Storage->get($self->session,$photo->{storageId});
|
||||
$storage->delete if $storage;
|
||||
}
|
||||
}
|
||||
$sth->finish;
|
||||
return $self->next::method;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 purgeRevision
|
||||
|
||||
Remove the storage locations for this revision of the Asset.
|
||||
|
||||
=cut
|
||||
|
||||
sub purgeRevision {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
foreach my $photo ( @{ $self->getPhotoData} ) {
|
||||
my $storage = WebGUI::Storage->get($session, $self-$photo->{storageId});
|
||||
$storage->delete if $storage;
|
||||
}
|
||||
return $self->next::method;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 setPhotoData ( $perlStructure )
|
||||
|
||||
Update the JSON stored in the object from its perl equivalent, and update the database
|
||||
as well via update. This deletes the cached copy of the equivalent perl structure.
|
||||
|
||||
=head3 $perlStructure
|
||||
|
||||
This should be an array of hashes. Photos will be in the order uploaded.
|
||||
The values in the hash will be metadata about the Photo, and the storageId
|
||||
that holds the image. Each storageId will hold only 1 file.
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
caption
|
||||
|
||||
=item *
|
||||
|
||||
byLine
|
||||
|
||||
=item *
|
||||
|
||||
alt
|
||||
|
||||
=item *
|
||||
|
||||
title
|
||||
|
||||
=item *
|
||||
|
||||
url
|
||||
|
||||
=item *
|
||||
|
||||
storageId
|
||||
|
||||
=back
|
||||
|
||||
subhash keys can be empty, or missing altogether. Shoot, you can really put anything you
|
||||
want in there as there's no valid content checking.
|
||||
|
||||
=cut
|
||||
|
||||
sub setPhotoData {
|
||||
my $self = shift;
|
||||
my $photoData = shift || [];
|
||||
##Convert to JSON
|
||||
my $photo = to_json($photoData);
|
||||
##Update the db.
|
||||
$self->update({photo => $photo});
|
||||
delete $self->{_photoData};
|
||||
return;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 setSize ( fileSize )
|
||||
|
||||
Set the size of this asset by including all the files in its storage
|
||||
location. C<fileSize> is an integer of additional bytes to include in
|
||||
the asset size.
|
||||
|
||||
=cut
|
||||
|
||||
sub setSize {
|
||||
my $self = shift;
|
||||
my $fileSize = shift || 0;
|
||||
my $session = $self->session;
|
||||
PHOTO: foreach my $photo (@{ $self->getPhotoData }) {
|
||||
my $storage = WebGUI::Storage->get($session, $photo->{storageId});
|
||||
next PHOTO unless defined $storage;
|
||||
foreach my $file (@{$storage->getFiles}) {
|
||||
$fileSize += $storage->getFileSize($file);
|
||||
}
|
||||
}
|
||||
return $self->next::method($fileSize);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 topic ( $topicAsset )
|
||||
|
||||
Tells the Story that it is being viewed from a Topic, and to behave
|
||||
accordingly. Returns a StoryTopic asset if set.
|
||||
|
||||
=head3 $topicAsset
|
||||
|
||||
The topic that is displaying this Story.
|
||||
|
||||
=cut
|
||||
|
||||
sub topic {
|
||||
my $self = shift;
|
||||
my $topic = shift;
|
||||
if (defined $topic) {
|
||||
$self->{_topic} = $topic;
|
||||
}
|
||||
return $self->{_topic};
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 update
|
||||
|
||||
Extend the superclass to make sure that the asset always stays hidden from navigation.
|
||||
|
||||
=cut
|
||||
|
||||
sub update {
|
||||
my $self = shift;
|
||||
my $properties = shift;
|
||||
return $self->next::method({%$properties, isHidden => 1});
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 validParent
|
||||
|
||||
Make sure that the current session asset is a StoryArchive for pasting and adding checks.
|
||||
|
||||
This is a class method.
|
||||
|
||||
=cut
|
||||
|
||||
sub validParent {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
return $session->asset && $session->asset->isa('WebGUI::Asset::Wobject::StoryArchive');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 view ( )
|
||||
|
||||
method called by the container www_view method.
|
||||
|
||||
=cut
|
||||
|
||||
##Keyword cloud generated by WebGUI::Keyword
|
||||
|
||||
sub view {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $var = $self->viewTemplateVariables();
|
||||
return $self->processTemplate($var,undef, $self->{_viewTemplate});
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 viewTemplateVars ( $var )
|
||||
|
||||
Add template variables to the existing template variables. This includes asset level variables.
|
||||
|
||||
=head3 $var
|
||||
|
||||
Template variables will be added onto this hash ref.
|
||||
|
||||
=cut
|
||||
|
||||
sub viewTemplateVariables {
|
||||
my ($self) = @_;
|
||||
my $session = $self->session;
|
||||
my $archive = $self->getArchive;
|
||||
my $var = $self->get;
|
||||
|
||||
if ($var->{highlights}) {
|
||||
my @highlights = split "\n+", $var->{highlights};
|
||||
foreach my $highlight (@highlights) {
|
||||
push @{ $var->{highlights_loop} }, { highlight => $highlight };
|
||||
}
|
||||
}
|
||||
|
||||
my $key = WebGUI::Keyword->new($session);
|
||||
my $keywords = $key->getKeywordsForAsset( { asArrayRef => 1, asset => $self });
|
||||
$var->{keyword_loop} = [];
|
||||
foreach my $keyword (@{ $keywords }) {
|
||||
push @{ $var->{keyword_loop} }, {
|
||||
keyword => $keyword,
|
||||
url => $archive->getUrl("func=view;keywords=".$session->url->escape($keyword)),
|
||||
};
|
||||
}
|
||||
$var->{updatedTime} = $self->formatDuration();
|
||||
$var->{updatedTimeEpoch} = $self->get('revisionDate');
|
||||
|
||||
$var->{crumb_loop} = $self->getCrumbTrail();
|
||||
my $photoData = $self->getPhotoData;
|
||||
$var->{photo_loop} = [];
|
||||
my $photoCounter = 0;
|
||||
PHOTO: foreach my $photo (@{ $photoData }) {
|
||||
next PHOTO unless $photo->{storageId};
|
||||
my $storage = WebGUI::Storage->get($session, $photo->{storageId});
|
||||
my $file = $storage->getFiles->[0];
|
||||
next PHOTO unless $file;
|
||||
my $imageUrl = $storage->getUrl($file);
|
||||
push @{ $var->{photo_loop} }, {
|
||||
imageUrl => $imageUrl,
|
||||
imageCaption => $photo->{caption},
|
||||
imageByline => $photo->{byLine},
|
||||
imageAlt => $photo->{alt},
|
||||
imageTitle => $photo->{title},
|
||||
imageLink => $photo->{url},
|
||||
};
|
||||
++$photoCounter;
|
||||
}
|
||||
$var->{hasPhotos} = $photoCounter;
|
||||
$var->{singlePhoto} = $photoCounter == 1;
|
||||
return $var;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_edit ( )
|
||||
|
||||
Web facing method which is the default edit page. Unless the method needs
|
||||
special handling or formatting, it does not need to be included in
|
||||
the module.
|
||||
|
||||
Overridden because the standard, autogenerated form is not used.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_edit {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return $session->privilege->insufficient() unless $self->canEdit;
|
||||
return $session->privilege->locked() unless $self->canEditIfLocked;
|
||||
return $self->getArchive->processStyle($self->getEditForm);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_showConfirmation ( )
|
||||
|
||||
Shows a confirmation message letting the user know their page has been submitted.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_showConfirmation {
|
||||
my $self = shift;
|
||||
my $i18n = WebGUI::International->new($self->session, 'Asset_Story');
|
||||
return $self->getArchive->processStyle('<p>'.$i18n->get('story received').'</p><p><a href="'.$self->getArchive->getUrl.'">'.$i18n->get('493','WebGUI').'</a></p>');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_view
|
||||
|
||||
Override www_view from asset because Stories inherit a style template from
|
||||
the Story Archive that contains them.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_view {
|
||||
my $self = shift;
|
||||
return $self->session->privilege->noAccess unless $self->canView;
|
||||
$self->session->http->sendHeader;
|
||||
$self->prepareView;
|
||||
return $self->getArchive->processStyle($self->view);
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
#vim:ft=perl
|
||||
|
|
@ -1210,7 +1210,8 @@ sub viewList {
|
|||
|
||||
### Build the event vars
|
||||
my $dtLast = $dtStart; # The DateTime of the last event
|
||||
for my $event (@events) {
|
||||
EVENT: for my $event (@events) {
|
||||
next EVENT unless $event && $event->canView();
|
||||
my ( %eventVar, %eventDate )
|
||||
= $self->getEventVars( $event );
|
||||
|
||||
|
|
|
|||
|
|
@ -437,7 +437,7 @@ sub appendTemplateVarsSearchForm {
|
|||
$var->{ searchForm_creationDate_after }
|
||||
= WebGUI::Form::dateTime( $session, {
|
||||
name => "creationDate_after",
|
||||
value => $form->get("creationDate_after","dateTime") || $oneYearAgo,
|
||||
value => $form->get("creationDate_after") || $oneYearAgo,
|
||||
});
|
||||
$var->{ searchForm_creationDate_before }
|
||||
= WebGUI::Form::dateTime( $session, {
|
||||
|
|
@ -1369,8 +1369,9 @@ search and display the results if necessary.
|
|||
|
||||
sub www_search {
|
||||
my $self = shift;
|
||||
my $form = $self->session->form;
|
||||
my $db = $self->session->db;
|
||||
my $session = $self->session;
|
||||
my $form = $session->form;
|
||||
my $db = $session->db;
|
||||
|
||||
my $var = $self->getTemplateVars;
|
||||
# NOTE: Search form is added as part of getTemplateVars()
|
||||
|
|
@ -1413,7 +1414,8 @@ sub www_search {
|
|||
;
|
||||
}
|
||||
|
||||
my $dateAfter = $form->get("creationDate_after", "dateTime");
|
||||
my $oneYearAgo = WebGUI::DateTime->new( $session, time )->add( years => -1 )->epoch;
|
||||
my $dateAfter = $form->get("creationDate_after") || $oneYearAgo;
|
||||
my $dateBefore = $form->get("creationDate_before", "dateTime");
|
||||
my $creationDate = {};
|
||||
if ($dateAfter) {
|
||||
|
|
@ -1463,7 +1465,7 @@ sub www_search {
|
|||
|
||||
$p->appendTemplateVars( $var );
|
||||
for my $result ( @{ $p->getPageData } ) {
|
||||
my $asset = WebGUI::Asset->newByDynamicClass( $self->session, $result->{assetId} );
|
||||
my $asset = WebGUI::Asset->newByDynamicClass( $session, $result->{assetId} );
|
||||
push @{ $var->{search_results} }, {
|
||||
%{ $asset->getTemplateVars },
|
||||
isAlbum => $asset->isa( 'WebGUI::Asset::Wobject::GalleryAlbum' ),
|
||||
|
|
|
|||
605
lib/WebGUI/Asset/Wobject/StoryArchive.pm
Normal file
605
lib/WebGUI/Asset/Wobject/StoryArchive.pm
Normal file
|
|
@ -0,0 +1,605 @@
|
|||
package WebGUI::Asset::Wobject::StoryArchive;
|
||||
|
||||
our $VERSION = "1.0.0";
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# WebGUI is Copyright 2001-2009 Plain Black Corporation.
|
||||
#-------------------------------------------------------------------
|
||||
# Please read the legal notices (docs/legal.txt) and the license
|
||||
# (docs/license.txt) that came with this distribution before using
|
||||
# this software.
|
||||
#-------------------------------------------------------------------
|
||||
# http://www.plainblack.com info@plainblack.com
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
use strict;
|
||||
use Tie::IxHash;
|
||||
use WebGUI::International;
|
||||
use WebGUI::Utility;
|
||||
use WebGUI::Asset::Story;
|
||||
use WebGUI::Asset::Wobject::Folder;
|
||||
use WebGUI::Paginator;
|
||||
use WebGUI::Keyword;
|
||||
use WebGUI::Search;
|
||||
use Class::C3;
|
||||
use base qw/WebGUI::AssetAspect::RssFeed WebGUI::Asset::Wobject/;
|
||||
use File::Path;
|
||||
|
||||
use constant DATE_FORMAT => '%c_%D_%y';
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 addChild ( )
|
||||
|
||||
Story Archive really only has Folders for children. When addChild is
|
||||
called, check the date to see which folder to use. If the correct folder
|
||||
does not exist, then make it.
|
||||
|
||||
=cut
|
||||
|
||||
sub addChild {
|
||||
my $self = shift;
|
||||
my ($properties) = @_;
|
||||
##Allow subclassing
|
||||
return undef unless $properties->{className} =~ /^WebGUI::Asset::Story/;
|
||||
my $todayFolder = $self->getFolder;
|
||||
return undef unless $todayFolder;
|
||||
my $story = $todayFolder->addChild(@_);
|
||||
return $story;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 canPostStories ( )
|
||||
|
||||
Determines whether or not a user can post stories to this Archive.
|
||||
|
||||
=head3 userId
|
||||
|
||||
An explicit userId to check against. If no userId is sent, then it
|
||||
will use the current session user instead.
|
||||
|
||||
=cut
|
||||
|
||||
sub canPostStories {
|
||||
my ($self, $userId) = @_;
|
||||
$userId ||= $self->session->user->userId;
|
||||
my $user = WebGUI::User->new($self->session, $userId);
|
||||
return $user->isInGroup($self->get("groupToPost")) || $self->canEdit($userId);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( )
|
||||
|
||||
defines wobject properties for New Wobject instances. You absolutely need
|
||||
this method in your new Wobjects. If you choose to "autoGenerateForms", the
|
||||
getEditForm method is unnecessary/redundant/useless.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_StoryArchive');
|
||||
my %properties;
|
||||
tie %properties, 'Tie::IxHash';
|
||||
%properties = (
|
||||
storiesPerPage => {
|
||||
tab => 'display',
|
||||
fieldType => 'integer',
|
||||
label => $i18n->get('stories per page'),
|
||||
hoverHelp => $i18n->get('stories per page help'),
|
||||
defaultValue => 25,
|
||||
},
|
||||
groupToPost => {
|
||||
tab => 'security',
|
||||
fieldType => 'group',
|
||||
label => $i18n->get('group to post'),
|
||||
hoverHelp => $i18n->get('group to post help'),
|
||||
defaultValue => '12',
|
||||
},
|
||||
templateId => {
|
||||
tab => 'display',
|
||||
fieldType => 'template',
|
||||
label => $i18n->get('template'),
|
||||
hoverHelp => $i18n->get('template help'),
|
||||
namespace => 'StoryArchive',
|
||||
defaultValue => 'yxD5ka7XHebPLD-LXBwJqw',
|
||||
},
|
||||
storyTemplateId => {
|
||||
tab => 'display',
|
||||
fieldType => 'template',
|
||||
label => $i18n->get('story template'),
|
||||
hoverHelp => $i18n->get('story template help'),
|
||||
namespace => 'Story',
|
||||
defaultValue => '3QpYtHrq_jmAk1FNutQM5A',
|
||||
},
|
||||
editStoryTemplateId => {
|
||||
tab => 'display',
|
||||
fieldType => 'template',
|
||||
label => $i18n->get('edit story template'),
|
||||
hoverHelp => $i18n->get('edit story template help'),
|
||||
namespace => 'Story/Edit',
|
||||
defaultValue => 'E3tzZjzhmYoNlAyP2VW33Q',
|
||||
},
|
||||
keywordListTemplateId => {
|
||||
tab => 'display',
|
||||
fieldType => 'template',
|
||||
label => $i18n->get('keyword list template'),
|
||||
hoverHelp => $i18n->get('keyword list template help'),
|
||||
namespace => 'StoryArchive/KeywordList',
|
||||
defaultValue => '0EAJ9EYb9ap2XwfrcXfdLQ',
|
||||
},
|
||||
archiveAfter => {
|
||||
tab => 'display',
|
||||
fieldType => 'interval',
|
||||
label => $i18n->get('archive after'),
|
||||
hoverHelp => $i18n->get('archive after help'),
|
||||
defaultValue => 31536000,
|
||||
},
|
||||
richEditorId => {
|
||||
tab => 'display',
|
||||
fieldType => 'selectRichEditor',
|
||||
label => $i18n->get('rich editor'),
|
||||
hoverHelp => $i18n->get('rich editor help'),
|
||||
defaultValue => 'PBrichedit000000000002',
|
||||
},
|
||||
approvalWorkflowId =>{
|
||||
tab => 'security',
|
||||
fieldType => 'workflow',
|
||||
defaultValue => 'pbworkflow000000000003',
|
||||
type => 'WebGUI::VersionTag',
|
||||
label => $i18n->get('approval workflow'),
|
||||
hoverHelp => $i18n->get('approval workflow help'),
|
||||
},
|
||||
);
|
||||
push(@{$definition}, {
|
||||
assetName=>$i18n->get('assetName'),
|
||||
icon=>'assets.gif',
|
||||
autoGenerateForms=>1,
|
||||
tableName=>'StoryArchive',
|
||||
className=>'WebGUI::Asset::Wobject::StoryArchive',
|
||||
properties=>\%properties,
|
||||
});
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 exportAssetCollateral (basePath, params, session)
|
||||
|
||||
Extended the master method in order to produce keyword files.
|
||||
|
||||
=cut
|
||||
|
||||
sub exportAssetCollateral {
|
||||
# Lots of copy/paste here from AssetExportHtml.pm, since none of the methods there were
|
||||
# directly useful without ginormous refactoring.
|
||||
my $self = shift;
|
||||
my $basepath = shift;
|
||||
my $args = shift;
|
||||
my $reportSession = shift;
|
||||
my $session = $self->session;
|
||||
|
||||
my $reporti18n = WebGUI::International->new($session, 'Asset');
|
||||
|
||||
my $basename = $basepath->basename;
|
||||
my $filedir;
|
||||
|
||||
# We want our keyword files to "appear" as children of the asset to avoid
|
||||
# clashing with multiple story archives.
|
||||
if ($basename eq 'index.html') {
|
||||
# Get the parent of the file index.html, which is the asset's directory.
|
||||
$filedir = $basepath->parent->absolute->stringify;
|
||||
}
|
||||
else {
|
||||
##Create a directory that has the same base
|
||||
my $dirname = $basename;
|
||||
$dirname =~ s/\.\w+$//;
|
||||
$filedir = $basepath->parent->subdir($dirname)->absolute->stringify;
|
||||
eval { File::Path::mkpath($filedir) };
|
||||
if($@) {
|
||||
WebGUI::Error->throw(error => "could not make directory " . $filedir);
|
||||
}
|
||||
}
|
||||
|
||||
if ( $reportSession && !$args->{quiet} ) {
|
||||
$reportSession->output->print('<br />');
|
||||
}
|
||||
|
||||
# open another session to handle printing...
|
||||
my $printSession = WebGUI::Session->open(
|
||||
$self->session->config->getWebguiRoot,
|
||||
$self->session->config->getFilename,
|
||||
undef,
|
||||
undef,
|
||||
$self->session->getId,
|
||||
);
|
||||
|
||||
my $keywordObj = WebGUI::Keyword->new($printSession);
|
||||
my $keywords = $keywordObj->findKeywords({
|
||||
asset => $self,
|
||||
limit => 50, ##This is based on the tagcloud setting
|
||||
});
|
||||
|
||||
my $listTemplate = WebGUI::Asset->new($session, $self->get('keywordListTemplateId'), 'WebGUI::Asset::Template');
|
||||
foreach my $keyword (@{ $keywords }) {
|
||||
##Keywords may not be URL safe, so urlize them
|
||||
my $keyword_url = $self->getKeywordFilename($keyword);
|
||||
my $dest = Path::Class::File->new($filedir, $keyword_url);
|
||||
|
||||
# tell the user which asset we're exporting.
|
||||
if ( $reportSession && !$args->{quiet} ) {
|
||||
my $message = sprintf $reporti18n->get('exporting page'), $dest->absolute->stringify;
|
||||
$reportSession->output->print(
|
||||
' ' . $message . '<br />');
|
||||
}
|
||||
|
||||
# next, get the contents, open the file, and write the contents to the file.
|
||||
my $fh = eval { $dest->open('>:utf8') };
|
||||
if($@) {
|
||||
$printSession->close;
|
||||
WebGUI::Error->throw(error => "can't open " . $dest->absolute->stringify . " for writing: $!");
|
||||
}
|
||||
$printSession->output->setHandle($fh);
|
||||
|
||||
my $storyIds = $keywordObj->getMatchingAssets({
|
||||
startAsset => $self,
|
||||
keyword => $keyword,
|
||||
isa => 'WebGUI::Asset::Story',
|
||||
rowsPerPage => 50,
|
||||
});
|
||||
my $listOfStories = [];
|
||||
STORYID: foreach my $storyId (@{ $storyIds }) {
|
||||
my $story = WebGUI::Asset->newByDynamicClass($session, $storyId);
|
||||
next STORYID unless $story;
|
||||
push @{ $listOfStories }, {
|
||||
title => $story->getTitle,
|
||||
url => $story->getUrl,
|
||||
};
|
||||
}
|
||||
my $var = {
|
||||
asset_loop => $listOfStories,
|
||||
keyword => $keyword,
|
||||
};
|
||||
my $output = $listTemplate->process($var);
|
||||
my $contents = $self->processStyle($output);
|
||||
$printSession->output->print($contents);
|
||||
|
||||
# tell the user we did this asset collateral correctly
|
||||
if ( $reportSession && !$args->{quiet} ) {
|
||||
$reportSession->output->print($reporti18n->get('done'));
|
||||
}
|
||||
$fh->flush;
|
||||
$fh->close;
|
||||
}
|
||||
$printSession->close;
|
||||
return $self->next::method($basepath, $args, $reportSession);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getFolder ( date )
|
||||
|
||||
Stories are stored in Folders under the Story Archive to prevent lineage issues.
|
||||
Gets the correct folder for stories. If the Folder does not exist, then it will
|
||||
be created and autocommitted. The autocommit is COMPLETELY automatic. This is
|
||||
because it's possible to gum up the Story submitting proces with a Folder under
|
||||
a different version tag.
|
||||
|
||||
=head3 date
|
||||
|
||||
There is one folder for each day that Stories are submitted. The requested date
|
||||
should be an epoch. If no date is passed, it will use the current time instead.
|
||||
|
||||
=cut
|
||||
|
||||
sub getFolder {
|
||||
my ($self, $date) = @_;
|
||||
my $session = $self->session;
|
||||
my $folderName = $session->datetime->epochToHuman($date, DATE_FORMAT);
|
||||
my $folderUrl = join '/', $self->getUrl, $folderName;
|
||||
my $folder = WebGUI::Asset->newByUrl($session, $folderUrl);
|
||||
return $folder if $folder;
|
||||
##The requested folder doesn't exist. Make it and autocommit it.
|
||||
|
||||
##For a fully automatic commit, save the current tag, create a new one
|
||||
##with the commit without approval workflow, commit it, then restore
|
||||
##the original if it exists
|
||||
my $oldVersionTag = WebGUI::VersionTag->getWorking($session, 'noCreate');
|
||||
my $newVersionTag = WebGUI::VersionTag->create($session, { workflowId => 'pbworkflow00000000003', });
|
||||
$newVersionTag->setWorking;
|
||||
|
||||
##Call SUPER because my addChild calls getFolder
|
||||
$folder = $self->SUPER::addChild({
|
||||
className => 'WebGUI::Asset::Wobject::Folder',
|
||||
title => $folderName,
|
||||
menuTitle => $folderName,
|
||||
url => $folderUrl,
|
||||
isHidden => 1,
|
||||
});
|
||||
$newVersionTag->commit();
|
||||
##Restore the old one, if it exists
|
||||
$oldVersionTag->setWorking() if $oldVersionTag;
|
||||
|
||||
##Get a new version of the asset from the db with the correct state
|
||||
$folder = WebGUI::Asset->newByUrl($session, $folderUrl);
|
||||
return $folder;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getKeywordFilename ( $keyword )
|
||||
|
||||
Returns the name for the file containing stories that match this keyword. Used
|
||||
in exportAssetCollateral, and in viewTemplateVariables.
|
||||
|
||||
=head3 $keyword
|
||||
|
||||
The keyword to generate a URL for.
|
||||
|
||||
=cut
|
||||
|
||||
sub getKeywordFilename {
|
||||
my ($self,$keyword) = @_;
|
||||
return $self->session->url->urlize('keyword_'.$keyword.'.html');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getKeywordStaticURL ( $keyword )
|
||||
|
||||
Returns the whole URL for the file containing stories that match this keyword. Used
|
||||
in exportAssetCollateral.
|
||||
|
||||
The goal of this method is to create a "safe" URL where all the keyword files can
|
||||
reside with no clashes. The best place is based on the URL for the StoryArchive.
|
||||
|
||||
=head3 $keyword
|
||||
|
||||
Generates a specific URL for $keyword.
|
||||
|
||||
=cut
|
||||
|
||||
sub getKeywordStaticURL {
|
||||
my ($self,$keyword) = @_;
|
||||
my $url = $self->getUrl;
|
||||
my @parts = split /\//, $url;
|
||||
my $lastPart = pop @parts;
|
||||
if (index $lastPart, '.' == -1) {
|
||||
return join '/', $self->getUrl, $self->getKeywordFilename($keyword);
|
||||
}
|
||||
else {
|
||||
$lastPart =~ s/\.[^.]*$//;
|
||||
return join '/', @parts, $lastPart, $self->getKeywordFilename($keyword);
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getRssFeedItems ( )
|
||||
|
||||
Returns an arrayref of hashrefs, containing information on stories
|
||||
for generating an RSS and Atom feeds.
|
||||
|
||||
=cut
|
||||
|
||||
sub getRssFeedItems {
|
||||
my $self = shift;
|
||||
my $stories = $self->getLineageIterator(['descendants'],{
|
||||
excludeClasses => ['WebGUI::Asset::Wobject::Folder'],
|
||||
orderByClause => 'creationDate desc, lineage',
|
||||
returnObjects => 1,
|
||||
limit => $self->get('itemsPerFeed'),
|
||||
});
|
||||
my $storyData = [];
|
||||
while (my $story = $stories->()) {
|
||||
push @{ $storyData }, $story->getRssData;
|
||||
}
|
||||
return $storyData;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 prepareView ( )
|
||||
|
||||
See WebGUI::Asset::prepareView() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub prepareView {
|
||||
my $self = shift;
|
||||
$self->SUPER::prepareView();
|
||||
my $template = WebGUI::Asset::Template->new($self->session, $self->get("templateId"));
|
||||
$template->prepare;
|
||||
$self->{_viewTemplate} = $template;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 view ( )
|
||||
|
||||
method called by the www_view method. Returns a processed template
|
||||
to be displayed within the page style.
|
||||
|
||||
=cut
|
||||
|
||||
sub view {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
|
||||
#This automatically creates template variables for all of your wobject's properties.
|
||||
my $mode = $session->form->hasParam('keyword')
|
||||
? 'keyword'
|
||||
: $session->form->hasParam('search')
|
||||
? 'search'
|
||||
: 'view';
|
||||
|
||||
my $var = $self->viewTemplateVariables($mode);
|
||||
|
||||
return $self->processTemplate($var, undef, $self->{_viewTemplate});
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 viewTemplateVars ( $mode )
|
||||
|
||||
Make template variables for the view template.
|
||||
|
||||
=head3 $mode
|
||||
|
||||
Whether to get assets in view mode, by time, or search mode, by keywords.
|
||||
|
||||
If the asset is being exported for HTML, the following changes are mode:
|
||||
|
||||
=over 4
|
||||
|
||||
=item *
|
||||
|
||||
The search form template variables are not generated.
|
||||
|
||||
=item *
|
||||
|
||||
The pagination variables are not generated.
|
||||
|
||||
=item *
|
||||
|
||||
The pagination size is set to 10 standard pages.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub viewTemplateVariables {
|
||||
my ($self, $mode) = @_;
|
||||
my $session = $self->session;
|
||||
my $keywords = $session->form->get('keyword');
|
||||
my $query = $session->form->get('query');
|
||||
my $exporting = $session->scratch->get('isExporting');
|
||||
my $p;
|
||||
my $var = $self->get();
|
||||
if ($mode eq 'keyword') {
|
||||
$var->{mode} = 'keyword';
|
||||
my $wordList = WebGUI::Keyword::string2list($keywords);
|
||||
my $key = WebGUI::Keyword->new($session);
|
||||
$p = $key->getMatchingAssets({
|
||||
startAsset => $self,
|
||||
keywords => $wordList,
|
||||
isa => 'WebGUI::Asset::Story',
|
||||
usePaginator => 1,
|
||||
rowsPerPage => $self->get('storiesPerPage'),
|
||||
});
|
||||
}
|
||||
elsif ($mode eq 'search') {
|
||||
$var->{mode} = 'search';
|
||||
my $search = WebGUI::Search->new($session);
|
||||
$search->search({
|
||||
keywords => $query,
|
||||
lineage => [ $self->get('lineage'), ],
|
||||
classes => [ qw/WebGUI::Asset::Story/, ],
|
||||
});
|
||||
$p = $search->getPaginatorResultSet($self->getUrl, $self->get('storiesPerPage'));
|
||||
}
|
||||
else {
|
||||
$var->{mode} = 'view';
|
||||
##Only return assetIds, we'll build data for the things that are actually displayed.
|
||||
my $storySql = $self->getLineageSql(['descendants'],{
|
||||
excludeClasses => ['WebGUI::Asset::Wobject::Folder'],
|
||||
orderByClause => 'creationDate desc, lineage',
|
||||
});
|
||||
my $storiesPerPage = $self->get('storiesPerPage');
|
||||
if ($exporting) {
|
||||
##10 pages worth of data on 1 page in export mode
|
||||
$storiesPerPage *= 10;
|
||||
}
|
||||
$p = WebGUI::Paginator->new($session, $self->getUrl, $storiesPerPage);
|
||||
$p->setDataByQuery($storySql);
|
||||
}
|
||||
my $storyIds = $p->getPageData();
|
||||
if (! $exporting ) {
|
||||
##Pagination variables aren't useful in export mode
|
||||
$p->appendTemplateVars($var);
|
||||
}
|
||||
$var->{date_loop} = [];
|
||||
my $lastStoryDate = '';
|
||||
my $datePointer = undef;
|
||||
##Only build objects for the assets that we need
|
||||
STORY: foreach my $storyId (@{ $storyIds }) {
|
||||
my $story = WebGUI::Asset->new($session, $storyId->{assetId}, $storyId->{className}, $storyId->{revisionDate});
|
||||
next STORY unless $story;
|
||||
my $creationDate = $story->get('creationDate');
|
||||
my ($creationDay,undef) = $session->datetime->dayStartEnd($creationDate);
|
||||
my $storyDate = $session->datetime->epochToHuman($creationDay, DATE_FORMAT);
|
||||
if ($storyDate ne $lastStoryDate) {
|
||||
push @{ $var->{date_loop} }, {};
|
||||
$datePointer = $var->{date_loop}->[-1];
|
||||
$datePointer->{epochDate} = $creationDay;
|
||||
$datePointer->{story_loop} = [];
|
||||
$lastStoryDate = $storyDate;
|
||||
}
|
||||
push @{$datePointer->{story_loop}}, {
|
||||
url => $story->getUrl,
|
||||
title => $story->getTitle,
|
||||
creationDate => $creationDate,
|
||||
}
|
||||
}
|
||||
|
||||
$var->{canPostStories} = $self->canPostStories;
|
||||
$var->{addStoryUrl} = $var->{canPostStories}
|
||||
? $self->getUrl('func=add;class=WebGUI::Asset::Story')
|
||||
: '';
|
||||
$var->{rssUrl} = $exporting ? $self->getStaticRssFeedUrl : $self->getRssFeedUrl;
|
||||
$var->{atomUrl} = $exporting ? $self->getStaticAtomFeedUrl : $self->getAtomFeedUrl;
|
||||
my $cloudOptions = {
|
||||
startAsset => $self,
|
||||
displayFunc => 'view',
|
||||
};
|
||||
##In export mode, tags should link to the pages generated during the collateral export
|
||||
if($exporting) {
|
||||
$cloudOptions->{urlCallback} = 'getKeywordStaticURL';
|
||||
$cloudOptions->{displayFunc} = '';
|
||||
}
|
||||
$var->{keywordCloud} = WebGUI::Keyword->new($session)->generateCloud($cloudOptions);
|
||||
if (! $exporting) {
|
||||
my $i18n = WebGUI::International->new($session, 'Asset');
|
||||
$var->{searchHeader} = WebGUI::Form::formHeader($session, { action => $self->getUrl })
|
||||
. WebGUI::Form::hidden($session, { name => 'func', value => 'view' });
|
||||
$var->{searchFooter} = WebGUI::Form::formFooter($session);
|
||||
$var->{searchButton} = WebGUI::Form::submit($session, { name => 'search', value => $i18n->get('search')});
|
||||
$var->{searchForm} = WebGUI::Form::text($session, { name => 'query', value => $query});
|
||||
}
|
||||
return $var;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_add ( )
|
||||
|
||||
The only real children of StoryArchive are Folders, which then hold Stories. So we intercept
|
||||
www_add, find the right folder to use, then allow that folder to continue on.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
sub www_add {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $form = $session->form;
|
||||
if ($form->get('class') ne 'WebGUI::Asset::Story') {
|
||||
$session->log->warn('Refusing to add '. $form->get('class'). ' to StoryArchive');
|
||||
return undef;
|
||||
}
|
||||
my $todayFolder = $self->getFolder;
|
||||
if (!$todayFolder) {
|
||||
$session->log->warn('Unable to get folder for today. Not adding Story');
|
||||
return undef;
|
||||
}
|
||||
$todayFolder->www_add;
|
||||
}
|
||||
|
||||
1;
|
||||
#vim:ft=perl
|
||||
267
lib/WebGUI/Asset/Wobject/StoryTopic.pm
Normal file
267
lib/WebGUI/Asset/Wobject/StoryTopic.pm
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
package WebGUI::Asset::Wobject::StoryTopic;
|
||||
|
||||
$VERSION = "1.0.0";
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# WebGUI is Copyright 2001-2009 Plain Black Corporation.
|
||||
#-------------------------------------------------------------------
|
||||
# Please read the legal notices (docs/legal.txt) and the license
|
||||
# (docs/license.txt) that came with this distribution before using
|
||||
# this software.
|
||||
#-------------------------------------------------------------------
|
||||
# http://www.plainblack.com info@plainblack.com
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
use strict;
|
||||
use Tie::IxHash;
|
||||
use WebGUI::International;
|
||||
use WebGUI::Utility;
|
||||
use WebGUI::Asset::Story;
|
||||
use Class::C3;
|
||||
use base qw/WebGUI::AssetAspect::RssFeed WebGUI::Asset::Wobject/;
|
||||
|
||||
use constant DATE_FORMAT => '%c_%D_%y';
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( )
|
||||
|
||||
defines wobject properties for New Wobject instances. You absolutely need
|
||||
this method in your new Wobjects. If you choose to "autoGenerateForms", the
|
||||
getEditForm method is unnecessary/redundant/useless.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_StoryTopic');
|
||||
my %properties;
|
||||
tie %properties, 'Tie::IxHash';
|
||||
%properties = (
|
||||
storiesPer => {
|
||||
tab => 'display',
|
||||
fieldType => 'integer',
|
||||
label => $i18n->get('stories per topic'),
|
||||
hoverHelp => $i18n->get('stories per topic help'),
|
||||
defaultValue => 15,
|
||||
},
|
||||
storiesShort => {
|
||||
tab => 'display',
|
||||
fieldType => 'integer',
|
||||
label => $i18n->get('stories short'),
|
||||
hoverHelp => $i18n->get('stories short help'),
|
||||
defaultValue => 5,
|
||||
},
|
||||
templateId => {
|
||||
tab => 'display',
|
||||
fieldType => 'template',
|
||||
label => $i18n->get('template'),
|
||||
hoverHelp => $i18n->get('template help'),
|
||||
filter => 'fixId',
|
||||
namespace => 'StoryTopic',
|
||||
defaultValue => 'A16v-YjWAShXWvSACsraeg',
|
||||
},
|
||||
storyTemplateId => {
|
||||
tab => 'display',
|
||||
fieldType => 'template',
|
||||
label => $i18n->get('story template'),
|
||||
hoverHelp => $i18n->get('story template help'),
|
||||
filter => 'fixId',
|
||||
namespace => 'Story',
|
||||
defaultValue => 'TbDcVLbbznPi0I0rxQf2CQ',
|
||||
},
|
||||
);
|
||||
push(@{$definition}, {
|
||||
assetName=>$i18n->get('assetName'),
|
||||
icon=>'assets.gif',
|
||||
autoGenerateForms=>1,
|
||||
tableName=>'StoryTopic',
|
||||
className=>'WebGUI::Asset::Wobject::StoryTopic',
|
||||
properties=>\%properties,
|
||||
});
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getRssFeedItems ( )
|
||||
|
||||
Returns an arrayref of hashrefs, containing information on stories
|
||||
for generating an RSS and Atom feeds.
|
||||
|
||||
=cut
|
||||
|
||||
sub getRssFeedItems {
|
||||
my ($self) = @_;
|
||||
my $session = $self->session;
|
||||
my $wordList = WebGUI::Keyword::string2list($self->get('keywords'));
|
||||
my $key = WebGUI::Keyword->new($session);
|
||||
my $storyIds = $key->getMatchingAssets({
|
||||
keywords => $wordList,
|
||||
isa => 'WebGUI::Asset::Story',
|
||||
rowsPerPage => $self->get('storiesPer'),
|
||||
});
|
||||
my $storyData = [];
|
||||
STORY: foreach my $storyId (@{ $storyIds }) {
|
||||
my $story = WebGUI::Asset->newByDynamicClass($session, $storyId);
|
||||
next STORY unless $story;
|
||||
push @{ $storyData }, $story->getRssData;
|
||||
}
|
||||
return $storyData;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 prepareView ( )
|
||||
|
||||
See WebGUI::Asset::prepareView() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub prepareView {
|
||||
my $self = shift;
|
||||
$self->SUPER::prepareView();
|
||||
my $template = WebGUI::Asset::Template->new($self->session, $self->get("templateId"));
|
||||
$template->prepare;
|
||||
$self->{_viewTemplate} = $template;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 view ( )
|
||||
|
||||
Method called by the www_view method. Returns a processed template
|
||||
to be displayed within the page style.
|
||||
|
||||
=cut
|
||||
|
||||
sub view {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
|
||||
#This automatically creates template variables for all of your wobject's properties.
|
||||
my $var = $self->viewTemplateVariables;
|
||||
|
||||
return $self->processTemplate($var, undef, $self->{_viewTemplate});
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 viewTemplateVars ( )
|
||||
|
||||
Make template variables for the view template.
|
||||
|
||||
=cut
|
||||
|
||||
sub viewTemplateVariables {
|
||||
my ($self) = @_;
|
||||
my $session = $self->session;
|
||||
my $exporting = $session->scratch->get('isExporting');
|
||||
my $numberOfStories = $self->{_standAlone}
|
||||
? $self->get('storiesPer')
|
||||
: $self->get('storiesShort');
|
||||
my $var = $self->get();
|
||||
my $wordList = WebGUI::Keyword::string2list($self->get('keywords'));
|
||||
my $key = WebGUI::Keyword->new($session);
|
||||
my $p = $key->getMatchingAssets({
|
||||
keywords => $wordList,
|
||||
isa => 'WebGUI::Asset::Story',
|
||||
usePaginator => 1,
|
||||
rowsPerPage => $numberOfStories,
|
||||
});
|
||||
my $storyIds = $p->getPageData();
|
||||
$var->{story_loop} = [];
|
||||
##Only build objects for the assets that we need
|
||||
STORY: foreach my $storyId (@{ $storyIds }) {
|
||||
my $story = WebGUI::Asset->new($session, $storyId->{assetId}, $storyId->{className}, $storyId->{revisionDate});
|
||||
next STORY unless $story;
|
||||
push @{$var->{story_loop}}, {
|
||||
url => ( $exporting
|
||||
? $story->getUrl
|
||||
: $session->url->append($self->getUrl, 'func=viewStory;assetId='.$storyId->{assetId}) ),
|
||||
title => $story->getTitle,
|
||||
creationDate => $story->get('creationDate'),
|
||||
}
|
||||
}
|
||||
|
||||
if ($self->{_standAlone}) {
|
||||
my $topStoryData = $storyIds->[0];
|
||||
shift @{ $var->{story_loop} };
|
||||
##Note, this could have saved from the loop above, but this looks more clean and encapsulated to me.
|
||||
my $topStory = WebGUI::Asset->new($session, $topStoryData->{assetId}, $topStoryData->{className}, $topStoryData->{revisionDate});
|
||||
$var->{topStoryTitle} = $topStory->getTitle;
|
||||
$var->{topStorySubtitle} = $topStory->get('subtitle');
|
||||
$var->{topStoryUrl} = $session->url->append($self->getUrl, 'func=viewStory;assetId='.$topStoryData->{assetId}),
|
||||
$var->{topStoryCreationDate} = $topStory->get('creationDate');
|
||||
##TODO: Photo variables
|
||||
my $photoData = $topStory->getPhotoData;
|
||||
PHOTO: foreach my $photo (@{ $photoData }) {
|
||||
next PHOTO unless $photo->{storageId};
|
||||
my $storage = WebGUI::Storage->get($session, $photo->{storageId});
|
||||
my $file = $storage->getFiles->[0];
|
||||
next PHOTO unless $file;
|
||||
my $imageUrl = $storage->getUrl($file);
|
||||
$var->{topStoryImageUrl} = $imageUrl;
|
||||
$var->{topStoryImageCaption} = $photo->{caption};
|
||||
$var->{topStoryImageByline} = $photo->{byLine};
|
||||
$var->{topStoryImageAlt} = $photo->{alt};
|
||||
$var->{topStoryImageTitle} = $photo->{title};
|
||||
$var->{topStoryImageLink} = $photo->{url};
|
||||
last PHOTO;
|
||||
}
|
||||
}
|
||||
$var->{standAlone} = $self->{_standAlone};
|
||||
$var->{rssUrl} = $exporting ? $self->getStaticRssFeedUrl : $self->getRssFeedUrl;
|
||||
$var->{atomUrl} = $exporting ? $self->getStaticAtomFeedUrl : $self->getAtomFeedUrl;
|
||||
|
||||
return $var;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_view ( )
|
||||
|
||||
Overside the method inherited from Wobject to set the mode so template
|
||||
variables are set correctly in viewTemplateVars.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
sub www_view {
|
||||
my $self = shift;
|
||||
$self->{_standAlone} = 1;
|
||||
return $self->SUPER::www_view;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_viewStory ( )
|
||||
|
||||
Display a story, set in the form variable assetId
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
sub www_viewStory {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $storyId = $session->form->get('assetId');
|
||||
my $story;
|
||||
if ($storyId) {
|
||||
$story = WebGUI::Asset->new($session, $storyId);
|
||||
}
|
||||
if (! $story) {
|
||||
my $notFound = WebGUI::Asset->getNotFound($session);
|
||||
$session->asset($notFound);
|
||||
return $notFound->www_view;
|
||||
}
|
||||
$story->topic($self);
|
||||
return $story->www_view;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
#vim:ft=perl
|
||||
|
|
@ -1240,6 +1240,7 @@ sub www_loadQuestions {
|
|||
if(! $self->session->form->param('shownsummary')){
|
||||
my ($summary,$html) = $self->getSummary();
|
||||
my $json = to_json( { type => 'summary', summary => $summary, html => $html });
|
||||
$self->session->http->setMimeType('application/json');
|
||||
return $json;
|
||||
}
|
||||
}
|
||||
|
|
@ -1328,6 +1329,7 @@ sub surveyEnd {
|
|||
#$self->session->http->setRedirect($url);
|
||||
#$self->session->http->setMimeType('application/json');
|
||||
my $json = to_json( { type => 'forward', url => $url } );
|
||||
$self->session->http->setMimeType('application/json');
|
||||
return $json;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -207,7 +207,8 @@ sub exportAssetCollateral {
|
|||
# Get the parent dir's *path* (essentially the name of the dir) relative to
|
||||
# its own parent dir.
|
||||
$filenameBase = $basepath->parent->relative( $basepath->parent->parent )->stringify;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
# Get the 1st ancestor, since the asset is a file recognized by apache, so
|
||||
# we want our files in the same dir.
|
||||
$filedir = $basepath->parent->absolute->stringify;
|
||||
|
|
@ -405,11 +406,19 @@ sub getStaticRssFeedUrl {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getFeed ()
|
||||
=head2 getFeed ( $feed )
|
||||
|
||||
Adds the syndicated items to the feed; returns the stringified edition.
|
||||
|
||||
Returns this feed so that XML::FeedPP methods can be chained on it.
|
||||
|
||||
TODO: convert dates?
|
||||
|
||||
=head3 $feed
|
||||
|
||||
An XML::FeedPP sub-object, XML::FeedPP::{Atom,Rss,Rdf} that will be filled
|
||||
with data from the Asset via the getRssFeedItems method.
|
||||
|
||||
=cut
|
||||
|
||||
sub getFeed {
|
||||
|
|
@ -421,7 +430,8 @@ sub getFeed {
|
|||
if (!$new_item->guid) {
|
||||
if ($new_item->link) {
|
||||
$new_item->guid( $new_item->link );
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$new_item->guid( $self->session->id->generate );
|
||||
$set_permalink_false = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,24 @@ sub exportCheckPath {
|
|||
Main logic hub for export functionality. This method calls most of the rest of
|
||||
the methods that handle exporting. Any exceptions thrown by the called methods
|
||||
are returned as strings to the caller. Returns a status description upon
|
||||
completion. Takes a hashref of arguments, containing the following keys:
|
||||
completion.
|
||||
|
||||
Internally, it sets two scratch variables in private sessions that it creates
|
||||
for exporting.
|
||||
|
||||
=over 4
|
||||
|
||||
=item exportMode
|
||||
|
||||
If this scratch variable exists, and is true, then the Asset is being exported.
|
||||
|
||||
=item exportUrl
|
||||
|
||||
This scratch variable is used by the Widget Macro.
|
||||
|
||||
=back
|
||||
|
||||
Takes a hashref of arguments, containing the following keys:
|
||||
|
||||
=head3 quiet
|
||||
|
||||
|
|
@ -173,6 +190,7 @@ false will do nothing.
|
|||
sub exportAsHtml {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
# set a scratch variable for Assets to know we're exporting
|
||||
my ($returnCode, $message);
|
||||
|
||||
# get the i18n object
|
||||
|
|
@ -287,8 +305,9 @@ sub exportAsHtml {
|
|||
my $exportSession = WebGUI::Session->open($self->session->config->getWebguiRoot, $self->session->config->getFilename);
|
||||
$exportSession->user( { userId => $userId } );
|
||||
|
||||
# set a scratch variable for widgets to know we're exporting
|
||||
$exportSession->scratch->set('exportUrl', $exportUrl);
|
||||
# set a scratch variable for Assets and widgets to know we're exporting
|
||||
$exportSession->scratch->set('isExporting', 1);
|
||||
$exportSession->scratch->set('exportUrl', $exportUrl);
|
||||
|
||||
my $asset = WebGUI::Asset->newByDynamicClass($exportSession, $assetId);
|
||||
my $fullPath = $asset->exportGetUrlAsPath;
|
||||
|
|
@ -519,6 +538,8 @@ Translates a URL into an appropriate path and filename for exporting. For
|
|||
example, given C<'/foo/bar/baz'>, will return C<'/foo/bar/baz/index.html'>
|
||||
provided the value of indexFile as given to exportAsHtml was C<'index.html'>.
|
||||
|
||||
Returns a Path::Class::File object.
|
||||
|
||||
=head3 url
|
||||
|
||||
URL of the asset we need an export path for
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ my $text = "";
|
|||
my $inside = {};
|
||||
|
||||
sub html2text {
|
||||
my $html = shift;
|
||||
my $html = shift() . " ";
|
||||
$text = "";
|
||||
$inside = {};
|
||||
my $tagHandler = sub {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ our $HELP = {
|
|||
{ name => 'isPrototype', },
|
||||
{ name => 'status', },
|
||||
{ name => 'assetSize', },
|
||||
{ name => 'keywords',
|
||||
description => 'keywords template var' },
|
||||
],
|
||||
fields => [],
|
||||
related => []
|
||||
|
|
|
|||
166
lib/WebGUI/Help/Asset_Story.pm
Normal file
166
lib/WebGUI/Help/Asset_Story.pm
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
package WebGUI::Help::Asset_Story;
|
||||
use strict;
|
||||
|
||||
our $HELP = {
|
||||
|
||||
'edit template' => {
|
||||
title => 'edit template',
|
||||
body => '',
|
||||
isa => [
|
||||
{ namespace => 'Asset_Template',
|
||||
tag => 'template variables'
|
||||
},
|
||||
],
|
||||
fields => [],
|
||||
variables => [
|
||||
{ name => 'formHeader',
|
||||
required => 1 },
|
||||
{ name => 'formTitle', },
|
||||
{ name => 'formFooter',
|
||||
required => 1 },
|
||||
{ name => 'titleForm', },
|
||||
{ name => 'headlineForm', },
|
||||
{ name => 'subtitleForm', },
|
||||
{ name => 'bylineForm', },
|
||||
{ name => 'locationForm', },
|
||||
{ name => 'keywordsForm', },
|
||||
{ name => 'summaryForm', },
|
||||
{ name => 'highlightsForm', },
|
||||
{ name => 'storyForm', },
|
||||
{ name => 'saveButton', },
|
||||
{ name => 'saveAndAddButton', },
|
||||
{ name => 'cancelButton', },
|
||||
{ name => 'photo_form_loop',
|
||||
variables => [
|
||||
{ name => 'imgUploadForm', },
|
||||
{ name => 'imgCaptionForm', },
|
||||
{ name => 'imgBylineForm', },
|
||||
{ name => 'imgAltForm', },
|
||||
{ name => 'imgTitleForm', },
|
||||
{ name => 'imgUrlForm', },
|
||||
{ name => 'imgDeleteForm', },
|
||||
],
|
||||
},
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
||||
'view template' => {
|
||||
title => 'view template',
|
||||
body => '',
|
||||
isa => [
|
||||
{ namespace => 'Asset_Template',
|
||||
tag => 'template variables'
|
||||
},
|
||||
],
|
||||
fields => [],
|
||||
variables => [
|
||||
{ name => 'highlights_loop',
|
||||
'variables' => [
|
||||
{ name => 'highlight', },
|
||||
],
|
||||
},
|
||||
{ name => 'keywords_loop',
|
||||
'variables' => [
|
||||
{ name => 'keyword', },
|
||||
{ name => 'url',
|
||||
description => 'keyword_url'
|
||||
},
|
||||
],
|
||||
},
|
||||
{ name => 'updatedTime', },
|
||||
{ name => 'updatedTimeEpoch', },
|
||||
{ name => 'crumb_loop',
|
||||
'variables' => [
|
||||
{ name => 'title',
|
||||
description => 'crumb_title'
|
||||
},
|
||||
{ name => 'url',
|
||||
description => 'crumb_url'
|
||||
},
|
||||
],
|
||||
},
|
||||
{ name => 'hasPhotos', },
|
||||
{ name => 'singlePhoto', },
|
||||
{ name => 'photo_loop',
|
||||
'variables' => [
|
||||
{ name => 'imageUrl', },
|
||||
{ name => 'imageCaption', },
|
||||
{ name => 'imageByline', },
|
||||
{ name => 'imageAlt', },
|
||||
{ name => 'imageTitle', },
|
||||
{ name => 'imageLink', },
|
||||
],
|
||||
},
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
||||
'story asset template variables' => {
|
||||
private => 1,
|
||||
title => 'story asset template variables title',
|
||||
body => '',
|
||||
isa => [
|
||||
{ namespace => 'Asset',
|
||||
tag => 'asset template asset variables'
|
||||
},
|
||||
],
|
||||
fields => [],
|
||||
variables => [
|
||||
{ name => 'headline',
|
||||
description => 'headline tmplvar',
|
||||
},
|
||||
{ name => 'subtitle',
|
||||
description => 'subtitle tmplvar',
|
||||
},
|
||||
{ name => 'byline',
|
||||
description => 'byline tmplvar',
|
||||
},
|
||||
{ name => 'updatedTime', },
|
||||
{ name => 'updatedTimeEpoch', },
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
||||
'story asset template variables' => {
|
||||
private => 1,
|
||||
title => 'story asset template variables title',
|
||||
body => '',
|
||||
isa => [
|
||||
{ namespace => 'Asset',
|
||||
tag => 'asset template asset variables'
|
||||
},
|
||||
],
|
||||
fields => [],
|
||||
variables => [
|
||||
{ name => 'headline',
|
||||
description => 'headline tmplvar',
|
||||
},
|
||||
{ name => 'subtitle',
|
||||
description => 'subtitle tmplvar',
|
||||
},
|
||||
{ name => 'byline',
|
||||
description => 'byline tmplvar',
|
||||
},
|
||||
{ name => 'location',
|
||||
description => 'location tmplvar',
|
||||
},
|
||||
{ name => 'highlights',
|
||||
description => 'highlights tmplvar',
|
||||
},
|
||||
{ name => 'story',
|
||||
description => 'story tmplvar',
|
||||
},
|
||||
{ name => 'photo',
|
||||
description => 'photo tmplvar',
|
||||
},
|
||||
{ name => 'storageId',
|
||||
description => 'storageId tmplvar',
|
||||
},
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
102
lib/WebGUI/Help/Asset_StoryArchive.pm
Normal file
102
lib/WebGUI/Help/Asset_StoryArchive.pm
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
package WebGUI::Help::Asset_StoryArchive;
|
||||
use strict;
|
||||
|
||||
our $HELP = {
|
||||
|
||||
'view template' => {
|
||||
title => 'view template',
|
||||
body => '',
|
||||
isa => [
|
||||
{ namespace => "Asset_StoryArchive",
|
||||
tag => "storyarchive asset template variables"
|
||||
},
|
||||
{ namespace => "Asset_Template",
|
||||
tag => "template variables"
|
||||
},
|
||||
{ namespace => "Asset",
|
||||
tag => "asset template"
|
||||
},
|
||||
{ tag => 'pagination template variables',
|
||||
namespace => 'WebGUI'
|
||||
},
|
||||
],
|
||||
fields => [],
|
||||
variables => [
|
||||
{ 'name' => 'date_loop',
|
||||
'variables' => [
|
||||
{ 'name' => 'epochDate' },
|
||||
{ 'name' => 'story_loop',
|
||||
'variables' => [
|
||||
{ 'name' => 'url' },
|
||||
{ 'name' => 'title' },
|
||||
{ 'name' => 'creationDate' },
|
||||
],
|
||||
},
|
||||
]
|
||||
},
|
||||
{ 'name' => 'searchHeader' },
|
||||
{ 'name' => 'searchForm' },
|
||||
{ 'name' => 'searchButton' },
|
||||
{ 'name' => 'searchFooter' },
|
||||
{ 'name' => 'canPostStories' },
|
||||
{ 'name' => 'addStoryUrl' },
|
||||
{ 'name' => 'rssUrl' },
|
||||
{ 'name' => 'atomUrl' },
|
||||
{ 'name' => 'keywordCloud' },
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
||||
'storyarchive asset template variables' => {
|
||||
private => 1,
|
||||
title => 'storyarchive asset template variables title',
|
||||
body => '',
|
||||
isa => [
|
||||
{ namespace => "Asset_Wobject",
|
||||
tag => "wobject template variables"
|
||||
},
|
||||
],
|
||||
fields => [],
|
||||
variables => [
|
||||
{ 'name' => 'storesPerPage',
|
||||
'description' => 'stories per page help',
|
||||
},
|
||||
{ 'name' => 'groupToPost', },
|
||||
{ 'name' => 'templateId', },
|
||||
{ 'name' => 'storyTemplateId', },
|
||||
{ 'name' => 'editStoryTemplateId', },
|
||||
{ 'name' => 'keywordListTemplateId', },
|
||||
{ 'name' => 'archiveAfter', },
|
||||
{ 'name' => 'richEditorId', },
|
||||
{ 'name' => 'approvalWorkflowId', },
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
||||
|
||||
'keyword list template' => {
|
||||
title => 'view template',
|
||||
body => '',
|
||||
isa => [
|
||||
{ namespace => "Asset_Template",
|
||||
tag => "template variables"
|
||||
},
|
||||
],
|
||||
fields => [],
|
||||
variables => [
|
||||
{ 'name' => 'asset_loop',
|
||||
'variables' => [
|
||||
{ 'name' => 'title',
|
||||
description => 'asset title' },
|
||||
{ 'name' => 'url',
|
||||
description => 'asset url' },
|
||||
]
|
||||
},
|
||||
{ 'name' => 'keyword' },
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
64
lib/WebGUI/Help/Asset_StoryTopic.pm
Normal file
64
lib/WebGUI/Help/Asset_StoryTopic.pm
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
package WebGUI::Help::Asset_StoryTopic;
|
||||
use strict;
|
||||
|
||||
our $HELP = {
|
||||
|
||||
'view template' => {
|
||||
title => 'view template',
|
||||
body => '',
|
||||
isa => [
|
||||
{ namespace => "Asset_StoryTopic",
|
||||
tag => "storytopic asset template variables"
|
||||
},
|
||||
{ namespace => "Asset_Template",
|
||||
tag => "template variables"
|
||||
},
|
||||
{ namespace => "Asset",
|
||||
tag => "asset template"
|
||||
},
|
||||
],
|
||||
fields => [],
|
||||
variables => [
|
||||
{ name => 'standAlone' },
|
||||
{ name => 'story_loop',
|
||||
variables => [
|
||||
{ name => 'url' },
|
||||
{ name => 'title' },
|
||||
{ name => 'creationDate' },
|
||||
],
|
||||
},
|
||||
{ name => 'topStoryTitle' },
|
||||
{ name => 'topStorySubtitle' },
|
||||
{ name => 'topStoryUrl' },
|
||||
{ name => 'topStoryCreationDate' },
|
||||
{ name => 'topStoryImageUrl' },
|
||||
{ name => 'topStoryImageCaption' },
|
||||
{ name => 'topStoryImageByline' },
|
||||
{ name => 'topStoryImageAlt' },
|
||||
{ name => 'topStoryImageTitle' },
|
||||
{ name => 'topStoryImageLink' },
|
||||
{ name => 'rssUrl' },
|
||||
{ name => 'atomUrl' },
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
||||
'storytopic asset template variables' => {
|
||||
private => 1,
|
||||
title => 'storytopic asset template variables title',
|
||||
body => '',
|
||||
isa => [
|
||||
{ namespace => "Asset_Wobject",
|
||||
tag => "wobject template variables"
|
||||
},
|
||||
],
|
||||
fields => [],
|
||||
variables => [
|
||||
],
|
||||
related => []
|
||||
},
|
||||
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
@ -256,7 +256,7 @@ sub getKeywordsForAsset {
|
|||
|
||||
=head2 getMatchingAssets ( { startAsset => $asset, keyword => $keyword } )
|
||||
|
||||
Returns an array reference of asset ids matching the params.
|
||||
Returns an array reference of asset ids matching the params. Assets are returned in order of creationDate.
|
||||
|
||||
=head3 startAsset
|
||||
|
||||
|
|
@ -283,6 +283,11 @@ A classname pattern to match. For example, if you provide 'WebGUI::Asset::Sku' t
|
|||
|
||||
Instead of returning an array reference of assetId's, return a paginator object.
|
||||
|
||||
=head3 rowsPerPage
|
||||
|
||||
If usePaginator is passed, then this variable will set the number of rows per page that the paginator uses.
|
||||
If usePaginator is not passed, then this variable will limit the number of assetIds that are returned.
|
||||
|
||||
=cut
|
||||
|
||||
sub getMatchingAssets {
|
||||
|
|
@ -331,14 +336,17 @@ sub getMatchingAssets {
|
|||
|
||||
# write the query
|
||||
my $query = 'select distinct assetKeyword.assetId from assetKeyword left join asset using (assetId)
|
||||
where '.join(' and ', @clauses).' order by creationDate desc';
|
||||
where '.join(' and ', @clauses).' order by creationDate desc, lineage';
|
||||
|
||||
# perform the search
|
||||
if ($options->{usePaginator}) {
|
||||
my $p = WebGUI::Paginator->new($self->session);
|
||||
my $p = WebGUI::Paginator->new($self->session, undef, $options->{rowsPerPage});
|
||||
$p->setDataByQuery($query, undef, undef, \@params);
|
||||
return $p;
|
||||
}
|
||||
elsif ($options->{rowsPerPage}) {
|
||||
$query .= ' limit '. $options->{rowsPerPage};
|
||||
}
|
||||
return $self->session->db->buildArrayRef($query, \@params);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -294,11 +294,13 @@ sub create {
|
|||
my $id = $headers->{messageId} || "WebGUI-" . $session->id->generate;
|
||||
if ($id !~ m/\@/) {
|
||||
my $domain = $from;
|
||||
$domain =~ s/.*\@//msx;
|
||||
$domain =~ s/^.*\@//msx;
|
||||
$domain =~ s/>$//msx;
|
||||
$id .= '@' . $domain;
|
||||
}
|
||||
if ($id !~ m/[<>]/msx) {
|
||||
$id = "<$id>";
|
||||
if ($id !~ m/^<.+?>$/msx) {
|
||||
$id =~ s/(^<)|(>$)//msxg;
|
||||
$id = "<".$id.">";
|
||||
}
|
||||
my $message = MIME::Entity->build(
|
||||
Type=>$type,
|
||||
|
|
|
|||
|
|
@ -713,7 +713,7 @@ sub setDataByQuery {
|
|||
my $sth;
|
||||
if ($unconditional) {
|
||||
$sth = $dbh->unconditionalRead($sql,$placeholders);
|
||||
return $sth->errorMessage if ($sth->errorCode > 0);
|
||||
return $sth->errorMessage if (defined $sth->errorCode);
|
||||
} else {
|
||||
$sth = $dbh->read($sql,$placeholders);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -828,8 +828,19 @@ sub set {
|
|||
}
|
||||
$properties->{fieldName} = $self->getId;
|
||||
|
||||
##Save the fieldType now. It can't be chacked against getFormControlClass now
|
||||
##because it will return the OLD formControlClass, not the new one that we need
|
||||
##to check against.
|
||||
my $originalFieldType = $self->get('fieldType');
|
||||
|
||||
# Update the record
|
||||
$db->setRow("userProfileField","fieldName",$properties);
|
||||
foreach my $key (keys %{$properties}) {
|
||||
$self->{_properties}{$key} = $properties->{$key};
|
||||
}
|
||||
|
||||
# If the fieldType has changed, modify the userProfileData column
|
||||
if ($properties->{fieldType} ne $self->get("fieldType")) {
|
||||
if ($properties->{fieldType} ne $originalFieldType) {
|
||||
# Create a copy of the new properties so we don't mess them up
|
||||
my $fieldClass = $self->getFormControlClass;
|
||||
eval "use $fieldClass;";
|
||||
|
|
@ -845,11 +856,6 @@ sub set {
|
|||
$db->write($sql);
|
||||
}
|
||||
|
||||
# Update the record
|
||||
$db->setRow("userProfileField","fieldName",$properties);
|
||||
foreach my $key (keys %{$properties}) {
|
||||
$self->{_properties}{$key} = $properties->{$key};
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -288,7 +288,7 @@ sub addFileFromFormPost {
|
|||
my $filename;
|
||||
my $attachmentCount = 1;
|
||||
foreach my $upload ($session->request->upload($formVariableName)) {
|
||||
$session->errorHandler->info("Trying to get " . $upload->filename);
|
||||
$session->errorHandler->info("Trying to get " . $upload->filename." from ".$formVariableName);
|
||||
return $filename
|
||||
if $attachmentCount > $attachmentLimit;
|
||||
my $clientFilename = $upload->filename;
|
||||
|
|
|
|||
104
lib/WebGUI/Workflow/Activity/ArchiveOldStories.pm
Normal file
104
lib/WebGUI/Workflow/Activity/ArchiveOldStories.pm
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
package WebGUI::Workflow::Activity::ArchiveOldStories;
|
||||
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2009 Plain Black Corporation.
|
||||
-------------------------------------------------------------------
|
||||
Please read the legal notices (docs/legal.txt) and the license
|
||||
(docs/license.txt) that came with this distribution before using
|
||||
this software.
|
||||
-------------------------------------------------------------------
|
||||
http://www.plainblack.com info@plainblack.com
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use base 'WebGUI::Workflow::Activity';
|
||||
use WebGUI::Asset;
|
||||
use WebGUI::Asset::Wobject::StoryArchive;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Workflow::Activity::ArchiveOldStories
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Uses the settings in the Story Archive to determine whether the Stories (and Folders) in those Story Archives should be archived.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
See WebGUI::Workflow::Activity for details on how to use any activity.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
These methods are available from this class:
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( session, definition )
|
||||
|
||||
See WebGUI::Workflow::Activity::defintion() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, "Workflow_Activity_ArchiveOldStories");
|
||||
push(@{$definition}, {
|
||||
name=>$i18n->get("activityName"),
|
||||
properties=> {}
|
||||
});
|
||||
return $class->SUPER::definition($session,$definition);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 execute ( )
|
||||
|
||||
See WebGUI::Workflow::Activity::execute() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub execute {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $epoch = $self->session->datetime->time();
|
||||
my $getAnArchive = WebGUI::Asset::Wobject::StoryArchive->getIsa($session);
|
||||
ARCHIVE: while (my $archive = $getAnArchive->()) {
|
||||
next ARCHIVE unless $archive && $archive->get("archiveAfter");
|
||||
my $archiveDate = $epoch - $archive->get("archiveAfter");
|
||||
my $folders = $archive->getLineage(
|
||||
['children'],
|
||||
{
|
||||
statusToInclude => ['approved'],
|
||||
whereClause => 'creationDate < '.$session->db->quote($archiveDate),
|
||||
returnObjects => 1,
|
||||
},
|
||||
);
|
||||
FOLDER: foreach my $folder (@{ $folders }) {
|
||||
next FOLDER unless $folder;
|
||||
my $stories = $folder->getLineage(
|
||||
['children'], { returnObjects => 1, },
|
||||
);
|
||||
STORY: foreach my $story (@{ $stories }) {
|
||||
next STORY unless $story;
|
||||
$story->update({ status => 'archived' });
|
||||
}
|
||||
$folder->update({ status => 'archived' });
|
||||
}
|
||||
}
|
||||
return $self->COMPLETE;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
|
|
@ -26,6 +26,12 @@ our $I18N = {
|
|||
context => q|help for the keywords property|
|
||||
},
|
||||
|
||||
'keywords template var' => {
|
||||
message => q|This will be a string with the keywords for this asset. Individual keywords will be joined with spaces, unless the keyword contains spaces, in which case it will be quoted.|,
|
||||
lastUpdated => 0,
|
||||
context => q|help for the keywords template variable|
|
||||
},
|
||||
|
||||
'add the missing page' => {
|
||||
message => q|Add the missing page.|,
|
||||
lastUpdated => 0,
|
||||
|
|
|
|||
451
lib/WebGUI/i18n/English/Asset_Story.pm
Normal file
451
lib/WebGUI/i18n/English/Asset_Story.pm
Normal file
|
|
@ -0,0 +1,451 @@
|
|||
package WebGUI::i18n::English::Asset_Story;
|
||||
use strict;
|
||||
|
||||
our $I18N = {
|
||||
|
||||
'assetName' => {
|
||||
message => q|Story|,
|
||||
context => q|Story, as in news story.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'headline' => {
|
||||
message => q|Headline|,
|
||||
context => q|Usually the title of a story. Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'headline help' => {
|
||||
message => q|Often the same as title. If left blank, it will take the headline from the title.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'headline tmplvar' => {
|
||||
message => q|The headline for the Story.|,
|
||||
context => q|Template variable help.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'subtitle' => {
|
||||
message => q|Subtitle|,
|
||||
context => q|Similar to headline, but usually contains more information. Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'subtitle help' => {
|
||||
message => q|Similar to headline, but usually contains more information.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'subtitle tmplvar' => {
|
||||
message => q|The subtitle from the Story.|,
|
||||
context => q|Template variable help.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'byline' => {
|
||||
message => q|By line|,
|
||||
context => q|Who wrote the story. Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'byline help' => {
|
||||
message => q|Who wrote the story.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'byline tmplvar' => {
|
||||
message => q|The byline from the Story.|,
|
||||
context => q|Template variable help.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'location' => {
|
||||
message => q|Location|,
|
||||
context => q|Where the story takes place. Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'location help' => {
|
||||
message => q|Where the story takes place.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'location tmplvar' => {
|
||||
message => q|The location from the Story.|,
|
||||
context => q|Template variable help.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'highlights' => {
|
||||
message => q|Story Highlights|,
|
||||
context => q|Bullet point level summaries from the story. Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'highlights help' => {
|
||||
message => q|Bullet point level items from the story. Enter 1 per line.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'highlights tmplvar' => {
|
||||
message => q|All of the highlights from the Story. Each highlight will be separated by a newline character.|,
|
||||
context => q|Template variable help.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'story' => {
|
||||
message => q|Story|,
|
||||
context => q|Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'story help' => {
|
||||
message => q|The story.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'story tmplvar' => {
|
||||
message => q|The story. Note that it may contain embedded content from the Rich Text Editor.|,
|
||||
context => q|Template variable help.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'save story' => {
|
||||
message => q|Save Story|,
|
||||
context => q|Button label in the Edit Story form.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'save and add another photo' => {
|
||||
message => q|Save and Add Another Photo|,
|
||||
context => q|Button label in the Edit Story form.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'story received' => {
|
||||
message => q|Your story has been received and is being processed so it can be added to the site. It will be available for further editing after being processed. Please be patient.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'edit template' => {
|
||||
message => q|Edit Story Template.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'formHeader' => {
|
||||
message => q|HTML code to begin the form for adding or editing a Story.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'formTitle' => {
|
||||
message => q|Internationalized title for this form.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'titleForm' => {
|
||||
message => q|Form for the user to enter a title for this story.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'headlineForm' => {
|
||||
message => q|Form for the user to enter a headline for this story.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'subtitleForm' => {
|
||||
message => q|Form for the user to enter a subtitle for this story.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'bylineForm' => {
|
||||
message => q|Form for the user to enter a byline for this story.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'locationForm' => {
|
||||
message => q|Form for the user to enter a location for this story.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'keywordsForm' => {
|
||||
message => q|Form for the user to enter keywords for this story.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'summaryForm' => {
|
||||
message => q|Form for the user to enter a summary of this story.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'highlightsForm' => {
|
||||
message => q|Form for the user to enter highlights for this story.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'storyForm' => {
|
||||
message => q|Form for the user to enter the actual story.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'saveButton' => {
|
||||
message => q|Button for the user to save the form.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'saveAndAddButton' => {
|
||||
message => q|Button for the user to save the form, and then reopen the edit form to add another photo.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'cancelButton' => {
|
||||
message => q|Button for the user to cancel this form without saving anything.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'formFooter' => {
|
||||
message => q|HTML code to end the form for adding or editing a Story.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'view template' => {
|
||||
message => q|View Story Template.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'highlights_loop' => {
|
||||
message => q|A loop containing all the highlights from the story.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'highlight' => {
|
||||
message => q|One highlight, without formatting or extra HTML.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'keywords_loop' => {
|
||||
message => q|A loop containing all the keywords from the story.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'keyword' => {
|
||||
message => q|One keyword, with no formatting.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'keyword_url' => {
|
||||
message => q|A URL to view all stories in this archive related to this keyword.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'crumb_loop' => {
|
||||
message => q|A loop containing the crumbtrail. The first element will be a link to the archive that contains the story. The last element will be the story, with title and url. If there are 3 elements, the middle element will be the topic.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'crumb_title' => {
|
||||
message => q|The title of a page in the crumb trail.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'crumb_url' => {
|
||||
message => q|The title of a page in the crumb trail.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'updatedTime' => {
|
||||
message => q|The time this Story was last updated, as a formatted duration, like 1 Hour(s) ago.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'updatedTimeEpoch' => {
|
||||
message => q|The time this Story was last updated, as an epoch.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'photo tmplvar' => {
|
||||
message => q|The photo JSON blob from the Story asset.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'storageId tmplvar' => {
|
||||
message => q|The photo JSON blob from the Story asset.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'ago' => {
|
||||
message => q|ago|,
|
||||
context => q|As in the phrase, Last updated 3 hours ago.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'storageId tmplvar' => {
|
||||
message => q|The photo JSON blob from the Story asset.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'story asset template variables title' => {
|
||||
message => q|Story Asset Template Variables.|,
|
||||
context => q|Title of a help page for asset level template variables.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'photo_form_loop' => {
|
||||
message => q|A loop containing subforms for all photos that have been loaded, and a blank form for uploading new photos.|,
|
||||
context => q|Template variable for edit form.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'imgUploadForm' => {
|
||||
message => q|A form field to upload an image.|,
|
||||
context => q|Template variable for edit form.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'imgCaptionForm' => {
|
||||
message => q|A form field for the caption for this image.|,
|
||||
context => q|Template variable for edit form.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'imgBylineForm' => {
|
||||
message => q|A form field for a by-line for this image.|,
|
||||
context => q|Template variable for edit form.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'imgAltForm' => {
|
||||
message => q|A form field for alternate text for the image, for the IMG tag ALT field.|,
|
||||
context => q|Template variable for edit form.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'imgTitleForm' => {
|
||||
message => q|A form field for the title for the image, for the IMG tag TITLE field.|,
|
||||
context => q|Template variable for edit form.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'imgUrlForm' => {
|
||||
message => q|A field for the URL for this image. If present, then the image will be rendered as a link to this URL.|,
|
||||
context => q|Template variable for edit form.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'imgDeleteForm' => {
|
||||
message => q|A field to delete the image, along with all data attached to it. This form will not be present in the set of variables in the loop for adding a new image.|,
|
||||
context => q|Template variable for edit form.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'photo caption' => {
|
||||
message => q|Photo Caption|,
|
||||
context => q|Label in the edit story form. Short for Photograph Caption.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'photo byline' => {
|
||||
message => q|Photo By Line|,
|
||||
context => q|Label in the edit story form. The person who took, or owns this photo.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'photo alt' => {
|
||||
message => q|Photo Alternate Text|,
|
||||
context => q|Label in the edit story form. Text for the ALT attribute of an IMG tag.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'photo title' => {
|
||||
message => q|Photo Alternate Title|,
|
||||
context => q|Label in the edit story form. Text for the TITLE attribute of an IMG tag.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'photo url' => {
|
||||
message => q|Photo URL|,
|
||||
context => q|Label in the edit story form. A link from the photo to more information about it, or referring to it.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'photo delete' => {
|
||||
message => q|Delete Photo|,
|
||||
context => q|Label in the edit story form. Request that the photo be deleted, and all information with it.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'photo_loop' => {
|
||||
message => q|A loop containing photos and information about the photos.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'imageUrl' => {
|
||||
message => q|The URL to the image.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'imageCaption' => {
|
||||
message => q|A caption for the image.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'imageByline' => {
|
||||
message => q|A byline for the image.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'imageAlt' => {
|
||||
message => q|Alternate text for the image, suitable for use as the ALT parameter for an IMG tag.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'imageTitle' => {
|
||||
message => q|Alternate text for the image, suitable for use as the TITLE parameter for an IMG tag.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'imageLink' => {
|
||||
message => q|A URL for the image to link to.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'hasPhotos' => {
|
||||
message => q|This template variable will be true if the Story has photos uploaded to it.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'singlePhoto' => {
|
||||
message => q|This template variable will be true if the Story has just 1 photo uploaded to it.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'imageLink' => {
|
||||
message => q|A URL for the image to link to.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'Source' => {
|
||||
message => q|Source|,
|
||||
context => q|Label for story template. Referring to who took, or who owns, a picture.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
302
lib/WebGUI/i18n/English/Asset_StoryArchive.pm
Normal file
302
lib/WebGUI/i18n/English/Asset_StoryArchive.pm
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
package WebGUI::i18n::English::Asset_StoryArchive;
|
||||
use strict;
|
||||
|
||||
our $I18N = {
|
||||
|
||||
'assetName' => {
|
||||
message => q|Story Archive|,
|
||||
context => q|An Asset that holds stories.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'stories per page' => {
|
||||
message => q|Stories Per Page|,
|
||||
context => q|Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'stories per page help' => {
|
||||
message => q|The number of stories displayed on a page. If the asset is exported as HTML, then the generated page will have 10 standard pages of stories.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'group to post' => {
|
||||
message => q|Group to Post|,
|
||||
context => q|Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'group to post help' => {
|
||||
message => q|The group allowed to add stories to this Story Archive.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'groupToPost' => {
|
||||
message => q|The GUID of the group allowed to add stories to this Story Archive.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'template' => {
|
||||
message => q|Story Archive Template|,
|
||||
context => q|Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'template help' => {
|
||||
message => q|The Template used to display the Story Archive.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'templateId' => {
|
||||
message => q|The GUID of the template used to display the Story Archive.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'story template' => {
|
||||
message => q|Story Template|,
|
||||
context => q|Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'story template help' => {
|
||||
message => q|The Template used to display Story assets from this Story Archive.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'storyTemplateId' => {
|
||||
message => q|The GUID of the template used to display the Story assets.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'edit story template' => {
|
||||
message => q|Edit Story Template|,
|
||||
context => q|Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'edit story template help' => {
|
||||
message => q|The Template used to add or edit Story assets.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'keyword list template' => {
|
||||
message => q|Keyword List Template|,
|
||||
context => q|Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'keyword list template help' => {
|
||||
message => q|The Template used to render the list of assets matching a keyword when this StoryArchive is exported.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'editStoryTemplateId' => {
|
||||
message => q|The GUID of the template used to add or edit Story assets.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'keywordListTemplateId' => {
|
||||
message => q|The GUID of the template used to render list of assets matching a keyword when this StoryArchive is exported.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'archive after' => {
|
||||
message => q|Archive Stories After|,
|
||||
context => q|Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'archive after help' => {
|
||||
message => q|After this time, Story assets will be archived and no longer show up in the list of Stories or feeds. Set to 0 to disable archiving.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'archiveAfter' => {
|
||||
message => q|Amount of time in seconds. After this time, Stories will be archived.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'rich editor' => {
|
||||
message => q|Rich Editor|,
|
||||
context => q|Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'rich editor help' => {
|
||||
message => q|The WYSIWIG editor used to edit the content of Story assets.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'richEditorId' => {
|
||||
message => q|The GUID of the WYSIWIG editor used to edit the content of Story assets.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'approval workflow' => {
|
||||
message => q|Story Approval Workflow|,
|
||||
context => q|Label in the edit screen and template.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'approval workflow help' => {
|
||||
message => q|Choose a workflow to be executed on each Story as it gets submitted.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'approvalWorkflowId' => {
|
||||
message => q|The GUID of the workflow to be executed on each Story as it gets submitted.|,
|
||||
context => q|Template variable|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'storyarchive asset template variables title' => {
|
||||
message => q|Story Archive Asset Template Variables.|,
|
||||
context => q|Title of a help page for asset level template variables.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'view template' => {
|
||||
message => q|Story Archive, View Template|,
|
||||
context => q|Title of a help page.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'date_loop' => {
|
||||
message => q|A loop containing stories in the date they were submitted, with subloops for each day. The loop is paginated.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'epochDate' => {
|
||||
message => q|The epoch that is the beginning of the day for a day where stories were submitted to the Story Archive.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'story_loop' => {
|
||||
message => q|A loop containing all stories there were submitted on the day given by epochDate.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'url' => {
|
||||
message => q|The URL to view a story.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'title' => {
|
||||
message => q|The title of a story.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'creationDate' => {
|
||||
message => q|The epoch date when this story was created, or submitted, to the Story Archive.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'add a story' => {
|
||||
message => q|Add a Story.|,
|
||||
context => q|label for the URL to add a story to the archive.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'searchHeader' => {
|
||||
message => q|HTML code for beginning the search form. This variable is empty when the Story Archive is being exported as HTML.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'searchForm' => {
|
||||
message => q|The text field where users can enter in keywords for the search. This variable is empty when the Story Archive is being exported as HTML.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'searchButton' => {
|
||||
message => q|Button with internationalized label for submitting the search form. This variable is empty when the Story Archive is being exported as HTML.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'searchFooter' => {
|
||||
message => q|HTML code for ending the search form. This variable is empty when the Story Archive is being exported as HTML.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'canPostStories' => {
|
||||
message => q|A boolean which is true if the user can post stories.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'addStoryUrl' => {
|
||||
message => q|The URL for the user to add a Story.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'rssUrl' => {
|
||||
message => q|The URL for the RSS feed for this Story Archive.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'atomUrl' => {
|
||||
message => q|The URL for the Atom feed for this Story Archive.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'keywordCloud' => {
|
||||
message => q|The tag cloud for the keywords for stories in this Story Archive.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'asset_loop' => {
|
||||
message => q|A loop containing up to the first 50 assets that match the keyword.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'asset title' => {
|
||||
message => q|The title of this asset.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'asset url' => {
|
||||
message => q|The title of this url.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'keyword' => {
|
||||
message => q|The keyword for this list of assets.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
176
lib/WebGUI/i18n/English/Asset_StoryTopic.pm
Normal file
176
lib/WebGUI/i18n/English/Asset_StoryTopic.pm
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
package WebGUI::i18n::English::Asset_StoryTopic;
|
||||
use strict;
|
||||
|
||||
our $I18N = {
|
||||
|
||||
'assetName' => {
|
||||
message => q|Story Topic|,
|
||||
context => q|An Asset that displays stories based on keywords.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'stories per topic' => {
|
||||
message => q|Stories Per Topic|,
|
||||
context => q|Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'stories per topic help' => {
|
||||
message => q|The number of stories displayed in RSS and Atom feeds from this Story Topic, and when viewing the Topic directly.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'stories short' => {
|
||||
message => q|Stories Per Page|,
|
||||
context => q|Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'stories short help' => {
|
||||
message => q|The number of stories displayed on a page.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'story template' => {
|
||||
message => q|Story Template|,
|
||||
context => q|Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'story template help' => {
|
||||
message => q|The Template used to display Story assets from this Story Topic.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'template' => {
|
||||
message => q|Main Template|,
|
||||
context => q|Label in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'template help' => {
|
||||
message => q|The Template used to display the Story Topic.|,
|
||||
context => q|Hoverhelp in the edit screen and template.|,
|
||||
lastUpdated => 0
|
||||
},
|
||||
|
||||
'story_loop' => {
|
||||
message => q|A loop containing the most recent stories for this topic.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'url' => {
|
||||
message => q|The URL to view a story.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'title' => {
|
||||
message => q|The title of a story.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'creationDate' => {
|
||||
message => q|The epoch date when this story was created, or submitted, to its Story Archive.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'topStoryUrl' => {
|
||||
message => q|The URL to view the top story.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'topStoryTitle' => {
|
||||
message => q|The title of the top story.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'topStorySubtitle' => {
|
||||
message => q|The subtitle of the top story.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'topStoryCreationDate' => {
|
||||
message => q|The epoch date when the top story was created, or submitted, to its Story Archive.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'topStoryImageCaption' => {
|
||||
message => q|The Caption of the first photo for the top story, if it exists.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'topStoryImageByline' => {
|
||||
message => q|The Byline of the first photo for the top story, if it exists.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'topStoryImageAlt' => {
|
||||
message => q|The alternate image text for the first photo for the top story, if it exists.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'topStoryImageTitle' => {
|
||||
message => q|The image title for the first photo for the top story, if it exists.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'topStoryImageLink' => {
|
||||
message => q|The link for the first photo for the top story, if it exists.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'topStoryImageUrl' => {
|
||||
message => q|The URL to the first photo for the top story, if it exists.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'standAlone' => {
|
||||
message => q|This variable will be true if the Story Topic is being viewed directly, by its URL. Otherwise, if it is viewed as part of a Page Layout or other Container, it will be false.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'view template' => {
|
||||
message => q|View Story Topic Template|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'storytopic asset template variables title' => {
|
||||
message => q|Story Topic Asset Template Variables|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'rssUrl' => {
|
||||
message => q|The URL for the RSS feed for this Story Archive.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'atomUrl' => {
|
||||
message => q|The URL for the Atom feed for this Story Archive.|,
|
||||
context => q|Template variable.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package WebGUI::i18n::English::Workflow_Activity_ArchiveOldStories;
|
||||
use strict;
|
||||
|
||||
our $I18N = {
|
||||
'activityName' => {
|
||||
message => q|Archive Old Stories|,
|
||||
context => q|The name of this workflow activity.|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
Loading…
Add table
Add a link
Reference in a new issue