565 lines
16 KiB
Perl
565 lines
16 KiB
Perl
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/;
|
|
|
|
=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.
|
|
|
|
=cut
|
|
|
|
sub addRevision {
|
|
my $self = shift;
|
|
my $newSelf = $self->next::method(@_);
|
|
|
|
my $newProperties = {
|
|
isHidden => 1,
|
|
};
|
|
|
|
if ($newSelf->get("storageId") && $newSelf->get("storageId") eq $self->get('storageId')) {
|
|
my $newStorage = $self->getStorageClass->get($self->session,$self->get("storageId"))->copy;
|
|
$newProperties->{storageId} = $newStorage->getId;
|
|
}
|
|
|
|
$newSelf->update($newProperties);
|
|
|
|
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 => 'text',
|
|
#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 => 'text',
|
|
#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 => '{}',
|
|
},
|
|
storageId => {
|
|
fieldType => 'hidden',
|
|
defaultValue => '',
|
|
noFormPost => 1,
|
|
},
|
|
);
|
|
push(@{$definition}, {
|
|
assetName => $i18n->get('assetName'),
|
|
icon => 'assets.gif',
|
|
tableName => 'Story',
|
|
className => 'WebGUI::Asset::Story',
|
|
properties => \%properties,
|
|
autoGenerateForms => 0,
|
|
});
|
|
return $class->SUPER::definition($session, $definition);
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 exportAssetData ( )
|
|
|
|
See WebGUI::AssetPackage::exportAssetData() for details.
|
|
Add the storage location to the export data.
|
|
|
|
=cut
|
|
|
|
sub exportAssetData {
|
|
my $self = shift;
|
|
my $data = $self->SUPER::exportAssetData;
|
|
push(@{$data->{storage}}, $self->get("storageId")) if ($self->get("storageId") ne "");
|
|
return $data;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=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 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 => $i18n->get('editing','Asset_WikiPage').' '.$title,
|
|
titleForm => WebGUI::Form::text($session, {
|
|
name => 'title',
|
|
value => $form->get('title') || $self->get('title'),
|
|
} ),
|
|
subTitleForm => WebGUI::Form::text($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::text($session, {
|
|
name => 'keywords',
|
|
value => $form->get('keywords') || WebGUI::Keyword->new($session)->getKeywordsForAsset({ asset => $self })
|
|
} ),
|
|
summaryForm => WebGUI::Form::textarea($session, {
|
|
name => 'summary',
|
|
value => $form->get('summary') || $self->get('summary')
|
|
} ),
|
|
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'),
|
|
}),
|
|
previewButton => WebGUI::Form::submit($session, {
|
|
name => 'saveAndPreview',
|
|
value => $i18n->get('save and preview'),
|
|
}),
|
|
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 => 'saveAndAddPhoto',
|
|
value => $i18n->get('save and add another photo'),
|
|
}),
|
|
};
|
|
if ($isNew) {
|
|
$var->{formHeader} .= WebGUI::Form::hidden($session, { name => 'assetId', value => 'new' })
|
|
. WebGUI::Form::hidden($session, { name => 'class', value => $form->process('class', 'className') });
|
|
}
|
|
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}) {
|
|
$self->{_photoData} = from_json($self->get('photo'));
|
|
}
|
|
return dclone($self->{_photoData});
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getStorageLocation ( [$noCreate] )
|
|
|
|
Returns the storage location for this Story. If it does not exist,
|
|
then it creates it via setStorageLocation. Subsequent lookups return
|
|
an internally cached Storage object to save time.
|
|
|
|
=head3 $noCreate
|
|
|
|
If $noCreate is true, then no storage location will be created, even
|
|
if it does not exist.
|
|
|
|
=cut
|
|
|
|
sub getStorageLocation {
|
|
my $self = shift;
|
|
my $noCreate = shift;
|
|
if (!exists $self->{_storageLocation} && !$noCreate) {
|
|
$self->setStorageLocation;
|
|
}
|
|
return $self->{_storageLocation};
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=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 processPropertiesFromFormPost ( )
|
|
|
|
Used to process properties from the form posted. Do custom things with
|
|
noFormPost fields here, or do whatever you want. This method is called
|
|
when /yourAssetUrl?func=editSave is requested/posted.
|
|
|
|
=cut
|
|
|
|
sub processPropertiesFromFormPost {
|
|
my $self = shift;
|
|
$self->SUPER::processPropertiesFromFormPost;
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 purge ( )
|
|
|
|
Cleaning up storage objects in all revisions.
|
|
|
|
=cut
|
|
|
|
sub purge {
|
|
my $self = shift;
|
|
my $sth = $self->session->db->read("select storageId from Story where assetId=".$self->session->db->quote($self->getId));
|
|
STORAGE: while (my ($storageId) = $sth->array) {
|
|
next STORAGE unless $storageId;
|
|
WebGUI::Storage->get($self->session,$storageId)->delete;
|
|
}
|
|
$sth->finish;
|
|
return $self->SUPER::purge;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 purgeRevision
|
|
|
|
Remove the storage location for this revision of the Asset.
|
|
|
|
=cut
|
|
|
|
sub purgeRevision {
|
|
my $self = shift;
|
|
$self->getStorageLocation->delete;
|
|
return $self->SUPER::purgeRevision;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 setPhotoData ( $perlStructure )
|
|
|
|
Returns the storage location for this Story. If it does not exist,
|
|
then it creates it via setStorageLocation. Subsequent lookups return
|
|
an internally cached Storage object to save time.
|
|
|
|
=head3 $perlStructure
|
|
|
|
This should be a hash of hashes. The keys will be names of photos in the
|
|
storage location for this Story. The values in the subhash will be
|
|
metadata about the Photo.
|
|
|
|
=item *
|
|
|
|
caption
|
|
|
|
=item *
|
|
|
|
byLine
|
|
|
|
=item *
|
|
|
|
alt
|
|
|
|
=item *
|
|
|
|
title
|
|
|
|
=item *
|
|
|
|
url
|
|
|
|
=back
|
|
|
|
subhash keys can be empty, or missing altogether. Shoot, you can really put anything you
|
|
want in there so there's no valid content checking.
|
|
|
|
=cut
|
|
|
|
sub setPhotoData {
|
|
my $self = shift;
|
|
my $photoData = shift || {};
|
|
my $photo = to_json($photoData);
|
|
$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 $storage = $self->getStorageLocation('noCreate');
|
|
if (defined $storage) {
|
|
foreach my $file (@{$storage->getFiles}) {
|
|
$fileSize += $storage->getFileSize($file);
|
|
}
|
|
}
|
|
return $self->SUPER::setSize($fileSize);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 setStorageLocation ( [ $storage] )
|
|
|
|
=head3 $storage
|
|
|
|
A storage location to use for this Story.
|
|
|
|
=cut
|
|
|
|
sub setStorageLocation {
|
|
my $self = shift;
|
|
my $storage = shift;
|
|
if (defined $storage) {
|
|
$self->{_storageLocation} = $storage;
|
|
}
|
|
elsif ($self->get("storageId") eq "") {
|
|
$self->{_storageLocation} = WebGUI::Storage->create($self->session);
|
|
$self->update({storageId=>$self->{_storageLocation}->getId});
|
|
}
|
|
else {
|
|
$self->{_storageLocation} = WebGUI::Storage->get($self->session,$self->get("storageId"));
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=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->SUPER::update({%$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 $var = $self->get; # $var is a hash reference.
|
|
$var->{controls} = $self->getToolbar;
|
|
return $self->processTemplate($var,undef, $self->{_viewTemplate});
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=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.
|
|
|
|
=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>');
|
|
}
|
|
|
|
|
|
1;
|
|
|
|
#vim:ft=perl
|