webgui/lib/WebGUI/Asset/Wobject/DataForm.pm
2009-06-02 19:34:18 +00:00

1656 lines
53 KiB
Perl

package WebGUI::Asset::Wobject::DataForm;
=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 Tie::IxHash;
use WebGUI::Form;
use WebGUI::HTMLForm;
use WebGUI::International;
use WebGUI::Mail::Send;
use WebGUI::Macro;
use WebGUI::Inbox;
use WebGUI::SQL;
use WebGUI::Asset::Wobject;
use WebGUI::Pluggable;
use WebGUI::DateTime;
use WebGUI::User;
use WebGUI::Group;
use WebGUI::AssetCollateral::DataForm::Entry;
use WebGUI::Form::SelectRichEditor;
use JSON ();
our @ISA = qw(WebGUI::Asset::Wobject);
=head1 NAME
Package WebGUI::Asset::Wobject::DataForm
=head1 DESCRIPTION
A subclass of lib/WebGUI/Wobject. DataForm creates custom forms to save data in the WebGUI database.
=head1 METHODS
These methods are available from this class:
=cut
#-------------------------------------------------------------------
sub _createForm {
my $self = shift;
my $data = shift;
my $value = shift;
# copy select entries
my %param = map { $_ => $data->{$_} } qw(name width extras vertical defaultValue options);
$param{value} = $value;
$param{size} = $param{width};
$param{height} = $data->{rows};
WebGUI::Macro::process($self->session, \( $param{defaultValue} ));
my $type = "\u$data->{type}";
my $class = "WebGUI::Form::$type";
eval {
WebGUI::Pluggable::load("WebGUI::Form::$type");
} || return undef;
if ($type eq "Checkbox") {
$param{defaultValue} = ($param{defaultValue} =~ /checked/i);
}
elsif ( $class->isa('WebGUI::Form::List') ) {
delete $param{size};
}
elsif ( $type eq 'HTMLArea' && $data->{htmlAreaRichEditor} ne '**Use_Default_Editor**') {
$param{richEditId} = $data->{htmlAreaRichEditor} ;
}
return $class->new($self->session, \%param);
}
#-------------------------------------------------------------------
sub _fieldAdminIcons {
my $self = shift;
my $fieldName = shift;
my $i18n = WebGUI::International->new($self->session,"Asset_DataForm");
my $output;
$output = $self->session->icon->delete('func=deleteFieldConfirm;fieldName='.$fieldName,$self->get("url"),$i18n->get(19))
unless $self->getFieldConfig($fieldName)->{isMailField};
$output .= $self->session->icon->edit('func=editField;fieldName='.$fieldName,$self->get("url"))
. $self->session->icon->moveUp('func=moveFieldUp;fieldName='.$fieldName,$self->get("url"))
. $self->session->icon->moveDown('func=moveFieldDown;fieldName='.$fieldName,$self->get("url"));
return $output;
}
#-------------------------------------------------------------------
sub _tabAdminIcons {
my $self = shift;
my $tabId = shift;
my $i18n = WebGUI::International->new($self->session,"Asset_DataForm");
my $output
= $self->session->icon->delete('func=deleteTabConfirm;tabId='.$tabId,$self->get("url"),$i18n->get(100))
. $self->session->icon->edit('func=editTab;tabId='.$tabId,$self->get("url"))
. $self->session->icon->moveLeft('func=moveTabLeft;tabId='.$tabId,$self->get("url"))
. $self->session->icon->moveRight('func=moveTabRight;tabId='.$tabId,$self->get("url"));
return $output;
}
#-------------------------------------------------------------------
sub _createTabInit {
my $self = shift;
my $tabCount = @{ $self->getTabOrder };
my $output = '<script type="text/javascript">var numberOfTabs = '.$tabCount.'; initTabs();</script>';
return $output;
}
#-------------------------------------------------------------------
sub defaultViewForm {
my $self = shift;
return ($self->get("defaultView") == 0);
}
sub defaultView {
my $self = shift;
return ($self->get("defaultView") == 0 ? 'form' : 'list');
}
sub currentView {
my $self = shift;
my $view = $self->{_mode} || $self->session->form->param('mode') || $self->defaultView;
return $view;
}
sub deleteField {
my $self = shift;
my $fieldName = shift;
my $fieldOrder = $self->getFieldOrder;
my $currentPos;
for ($currentPos = 0; $currentPos < @$fieldOrder; $currentPos++) {
last
if $fieldName eq $fieldOrder->[$currentPos];
}
splice @$fieldOrder, $currentPos, 1;
delete $self->getFieldConfig->{$fieldName};
$self->_saveFieldConfig;
return 1;
}
sub deleteTab {
my $self = shift;
my $tabId = shift;
my $tabOrder = $self->getTabOrder;
my $currentPos;
for ($currentPos = 0; $currentPos < @$tabOrder; $currentPos++) {
last
if $tabId eq $tabOrder->[$currentPos];
}
splice @$tabOrder, $currentPos, 1;
delete $self->getTabConfig->{$tabId};
for my $field (grep { $_->{tabId} eq $tabId } values %{ $self->getFieldConfig }) {
$field->{tabId} = undef;
}
$self->_saveTabConfig;
return 1;
}
sub getContentLastModified {
my $self = shift;
if ($self->currentView eq 'list' || $self->session->form->process('entryId')) {
return time;
}
return $self->SUPER::getContentLastModified;
}
sub renameField {
my $self = shift;
my $oldName = shift;
my $newName = shift;
my $fieldOrder = $self->getFieldOrder;
my $currentPos;
for my $fieldName (@$fieldOrder) {
if ($fieldName eq $oldName) {
$fieldName = $newName;
}
}
$self->getFieldConfig->{$newName} = $self->getFieldConfig->{$oldName};
delete $self->getFieldConfig->{$oldName};
return $self->getFieldConfig->{$newName}{name} = $newName;
}
sub _saveFieldConfig {
my $self = shift;
my @config = map {
$self->getFieldConfig($_)
} @{ $self->getFieldOrder };
my $data = JSON::to_json(\@config);
$self->update({fieldConfiguration => $data});
}
sub _saveTabConfig {
my $self = shift;
my @config = map {
$self->getTabConfig($_)
} @{ $self->getTabOrder };
my $data = JSON::to_json(\@config);
$self->update({tabConfiguration => $data});
}
#-------------------------------------------------------------------
=head2 definition ( session, [definition] )
Returns an array reference of definitions. Adds tableName, className, properties to array definition.
=head3 definition
An array of hashes to prepend to the list
=cut
sub definition {
my $class = shift;
my $session = shift;
my $definition = shift;
my $i18n = WebGUI::International->new($session,"Asset_DataForm");
my %properties;
# populate hash of Rich Editors and add an entry to the list to use the default
my $selectRichEditor = WebGUI::Form::SelectRichEditor->new($session,{}) ;
my $richEditorOptions = $selectRichEditor->getOptions() ;
$richEditorOptions->{'**Use_Default_Editor**'} = $i18n->get("Use Default Rich Editor");
tie %properties, 'Tie::IxHash';
%properties = (
templateId => {
fieldType => 'template',
defaultValue => 'PBtmpl0000000000000141',
namespace => 'DataForm',
tab => 'display',
label => $i18n->get(82),
hoverHelp => $i18n->get('82 description'),
afterEdit => 'func=edit',
},
htmlAreaRichEditor =>{
fieldType=>"selectBox",
defaultValue=>0,
options=>$richEditorOptions,
tab=>'display',
label=>$i18n->get('htmlAreaRichEditor'),
hoverHelp=>$i18n->get('htmlAreaRichEditor description'),
},
emailTemplateId => {
fieldType => "template",
defaultValue => 'PBtmpl0000000000000085',
namespace => 'DataForm',
tab => 'display',
label => $i18n->get(80),
hoverHelp => $i18n->get('80 description'),
afterEdit => 'func=edit',
},
acknowlegementTemplateId => {
fieldType => "template",
defaultValue => 'PBtmpl0000000000000104',
namespace => 'DataForm',
tab => 'display',
label => $i18n->get(81),
hoverHelp => $i18n->get('81 description'),
afterEdit => 'func=edit',
},
listTemplateId => {
fieldType => "template",
defaultValue => 'PBtmpl0000000000000021',
namespace => 'DataForm/List',
tab => 'display',
label => $i18n->get(87),
hoverHelp => $i18n->get('87 description'),
afterEdit => 'func=edit',
},
defaultView => {
fieldType => "radioList",
defaultValue => 0,
options => {
0 => $i18n->get('data form'),
1 => $i18n->get('data list'),
},
label => $i18n->get('defaultView'),
hoverHelp => $i18n->get('defaultView description'),
tab => 'display',
},
acknowledgement => {
fieldType => "HTMLArea",
defaultValue => undef,
tab => 'properties',
label => $i18n->get(16),
hoverHelp => $i18n->get('16 description'),
},
mailData => {
fieldType => "yesNo",
defaultValue => 0,
tab => 'display',
label => $i18n->get(74),
hoverHelp => $i18n->get('74 description'),
},
storeData => {
fieldType => "yesNo",
defaultValue => 1,
tab => 'display',
label => $i18n->get('store data'),
hoverHelp => $i18n->get('store data description'),
},
mailAttachments => {
fieldType => 'yesNo',
defaultValue => 0,
tab => 'properties',
label => $i18n->get("mail attachments"),
hoverHelp => $i18n->get("mail attachments description"),
},
groupToViewEntries => {
fieldType => "group",
defaultValue => 7,
tab => 'security',
label => $i18n->get('group to view entries'),
hoverHelp => $i18n->get('group to view entries description'),
},
useCaptcha => {
tab => 'properties',
fieldType => "yesNo",
defaultValue => 0,
label => $i18n->get('editForm useCaptcha label'),
hoverHelp => $i18n->get('editForm useCaptcha description'),
},
workflowIdAddEntry => {
tab => "properties",
fieldType => "workflow",
defaultValue => undef,
type => "WebGUI::AssetCollateral::DataForm::Entry",
none => 1,
label => $i18n->get('editForm workflowIdAddEntry label'),
hoverHelp => $i18n->get('editForm workflowIdAddEntry description'),
},
fieldConfiguration => {
fieldType => 'hidden',
},
tabConfiguration => {
fieldType => 'hidden',
},
);
my @defFieldConfig = (
{
name=>"from",
label=>$i18n->get(10),
status=>"editable",
isMailField=>1,
width=>0,
type=>"email",
},
{
name=>"to",
label=>$i18n->get(11),
status=>"hidden",
isMailField=>1,
width=>0,
type=>"email",
defaultValue=>$session->setting->get("companyEmail"),
},
{
name=>"cc",
label=>$i18n->get(12),
status=>"hidden",
isMailField=>1,
width=>0,
type=>"email",
},
{
name=>"bcc",
label=>$i18n->get(13),
status=>"hidden",
isMailField=>1,
width=>0,
type=>"email",
},
{
name=>"subject",
label=>$i18n->get(14),
status=>"editable",
isMailField=>1,
width=>0,
type=>"text",
defaultValue=>$i18n->get(2),
},
);
$properties{fieldConfiguration}{defaultValue} = JSON::to_json(\@defFieldConfig);
push @$definition, {
assetName => $i18n->get('assetName'),
uiLevel => 5,
tableName => 'DataForm',
icon => 'dataForm.gif',
className => __PACKAGE__,
properties => \%properties,
autoGenerateForms => 1,
};
return $class->SUPER::definition($session, $definition);
}
sub _cacheFieldConfig {
my $self = shift;
if (!$self->{_fieldConfig}) {
my $jsonData = $self->get("fieldConfiguration");
my $fieldData;
if ($jsonData && eval { $jsonData = JSON::from_json($jsonData) ; 1 }) {
# jsonData is an array in the order the fields should be
$self->{_fieldConfig} = {};
$self->{_fieldOrder} = [];
FIELD: foreach my $field (@{ $jsonData } ) {
next FIELD unless ref $field eq 'HASH';
$self->{_fieldConfig}->{$field->{name}} = $field;
push @{ $self->{_fieldOrder} }, $field->{name};
}
}
else {
$self->{_fieldConfig} = {};
$self->{_fieldOrder} = [];
}
}
return 1;
}
sub _cacheTabConfig {
my $self = shift;
if (!$self->{_tabConfig}) {
my $jsonData = $self->get("tabConfiguration");
my $fieldData;
if ($jsonData && eval { $jsonData = JSON::from_json($jsonData) ; 1 }) {
# jsonData is an array in the order the fields should be
$self->{_tabConfig} = {
map { $_->{tabId}, $_ } @{ $jsonData }
};
$self->{_tabOrder} = [
map { $_->{tabId} } @{ $jsonData }
];
}
else {
$self->{_tabConfig} = {};
$self->{_tabOrder} = [];
}
}
return 1;
}
sub getFieldConfig {
my $self = shift;
my $field = shift;
$self->_cacheFieldConfig;
if ($field) {
return $self->{_fieldConfig}{$field};
}
else {
return $self->{_fieldConfig};
}
}
sub getFieldOrder {
my $self = shift;
$self->_cacheFieldConfig;
return $self->{_fieldOrder};
}
sub getTabConfig {
my $self = shift;
my $tabId = shift;
$self->_cacheTabConfig;
if ($tabId) {
return $self->{_tabConfig}{$tabId};
}
else {
return $self->{_tabConfig};
}
}
sub getTabOrder {
my $self = shift;
$self->_cacheTabConfig;
return $self->{_tabOrder};
}
#-------------------------------------------------------------------
sub deleteAttachedFiles {
my $self = shift;
my %params = @_;
my $entryData = $params{entryData};
my $entryId = $params{entryId};
my $fields = $self->getFieldOrder;
my $fieldConfig = $self->getFieldConfig;
if ($entryId) {
my $entry = $self->entryClass->new($self, $entryId);
$entryData = $entry->fields;
}
if ($entryData) {
for my $field ( @$fields ) {
my $form = $self->_createForm($fieldConfig->{$field}, $entryData->{$field});
if ($form->can('getStorageLocation')) {
my $storage = $form->getStorageLocation;
$storage->delete if $storage;
}
}
}
else {
my $entryIter = $self->entryClass->iterateAll($self);
while (my $entry = $entryIter->()) {
my $entryData = $entry->fields;
for my $field (@{ $fields }) {
my $form = $self->_createForm($fieldConfig->{$field}, $entryData->{$field});
if ($form->can('getStorageLocation')) {
my $storage = $form->getStorageLocation;
$storage->delete if $storage;
}
}
}
}
}
#-------------------------------------------------------------------
sub getAttachedFiles {
my $self = shift;
my $entryData = shift;
my $fieldConfig = $self->getFieldConfig;
my @paths;
for my $field ( values %{$fieldConfig} ) {
my $form = $self->_createForm($field, $entryData->field($field->{name}));
if ($form->can('getStorageLocation')) {
my $storage = $form->getStorageLocation;
if ($storage) {
push @paths, $storage->getPath($storage->getFiles->[0]);
}
}
}
return \@paths;
}
#-------------------------------------------------------------------
sub getListTemplateVars {
my $self = shift;
my $var = shift;
my $i18n = WebGUI::International->new($self->session,"Asset_DataForm");
$var->{"back.url"} = $self->getFormUrl;
$var->{"back.label"} = $i18n->get('go to form');
my $fieldConfig = $self->getFieldConfig;
my @fieldLoop = map {
+{
'field.name' => $fieldConfig->{$_}{name},
'field.label' => $fieldConfig->{$_}{label},
'field.isMailField' => $fieldConfig->{$_}{isMailField},
'field.type' => $fieldConfig->{$_}{type},
}
} @{ $self->getFieldOrder };
$var->{field_loop} = \@fieldLoop;
my @recordLoop;
my $entryIter = $self->entryClass->iterateAll($self);
while ( my $entry = $entryIter->() ) {
my $entryData = $entry->fields;
my @dataLoop;
for my $fieldName ( @{ $self->getFieldOrder } ) {
my $field = $fieldConfig->{$fieldName};
my $form = $self->_createForm($field, $entryData->{$fieldName});
push @dataLoop, {
"record.data.name" => $field->{name},
"record.data.label" => $field->{label},
"record.data.value" => $form->getValueAsHtml,
"record.data.isMailField" => $field->{isMailField},
"record_data_type" => $field->{type},
};
}
push @recordLoop, {
"record.ipAddress" => $entry->ipAddress,
"record.edit.url" => $self->getFormUrl("func=view;entryId=".$entry->getId),
"record.edit.icon" => $self->session->icon->edit("func=view;entryId=".$entry->getId, $self->get('url')),
"record.delete.url" => $self->getUrl("func=deleteEntry;entryId=".$entry->getId),
"record.delete.icon" => $self->session->icon->delete("func=deleteEntry;entryId=".$entry->getId, $self->get('url'), $i18n->get('Delete entry confirmation')),
"record.username" => $entry->username,
"record.userId" => $entry->userId,
"record.submissionDate.epoch" => $entry->submissionDate->epoch,
"record.submissionDate.human" => $entry->submissionDate->cloneToUserTimeZone->webguiDate,
"record.entryId" => $entry->getId,
"record.data_loop" => \@dataLoop
};
}
$var->{record_loop} = \@recordLoop;
return $var;
}
#-------------------------------------------------------------------
sub getFormUrl {
my $self = shift;
my $params = shift;
my $url = $self->getUrl;
unless ($self->defaultViewForm) {
$url = $self->session->url->append($url, 'mode=form');
}
if ($params) {
$url = $self->session->url->append($url, $params);
}
return $url;
}
#-------------------------------------------------------------------
=head2 getListUrl( params )
Get url of list of entries
=head3 params
Name value pairs of URL paramters in the form of:
name1=value1;name2=value2;name3=value3
=cut
sub getListUrl {
my $self = shift;
my $params = shift;
my $url = $self->getUrl;
if ($self->defaultViewForm) {
$url = $self->session->url->append($url, 'mode=list');
}
if ($params) {
$url = $self->session->url->append($url, $params);
}
return $url;
}
#-------------------------------------------------------------------
# Template variables for normal form view and email message
sub getRecordTemplateVars {
my $self = shift;
my $var = shift;
my $entry = shift;
my $session = $self->session;
my $i18n = WebGUI::International->new($session, 'Asset_DataForm');
$var->{'back.url'} = $self->getUrl;
$var->{'back.label'} = $i18n->get(18);
$var->{'error_loop'} ||= [];
$var->{'form.start'}
= WebGUI::Form::formHeader($session, {action => $self->getUrl})
. WebGUI::Form::hidden($session, {name => 'func', value => 'process'})
;
my $fields = $self->getFieldConfig;
# If we have an entry, we're doing this based on existing data
my $entryData;
if ($entry) {
my $entryId = $entry->getId;
$var->{'form.start'} .= WebGUI::Form::hidden($session,{name => "entryId", value => $entryId});
$entryData = $entry->fields;
my $date = $entry->submissionDate->cloneToUserTimeZone;
$var->{'ipAddress' } = $entry->ipAddress;
$var->{'username' } = $entry->username;
$var->{'userId' } = $entry->userId;
$var->{'date' } = $date->webguiDate;
$var->{'epoch' } = $date->epoch;
$var->{'edit.URL' } = $self->getFormUrl('entryId=' . $entryId);
$var->{'delete.url' } = $self->getUrl('func=deleteEntry;entryId=' . $entryId);
$var->{'delete.label' } = $i18n->get(90);
$var->{'entryId' } = $entryId;
}
my $func = $session->form->process('func');
my $ignoreForm = $func eq 'editSave' || $func eq 'editFieldSave';
my %tabById;
my @tabLoop;
my $tabIdx = 0;
for my $tabId (@{ $self->getTabOrder} ) {
$tabIdx++;
my $tab = $self->getTabConfig($tabId);
my $tabVars = {
"tab.start" => '<div id="tabcontent' . $tabIdx . '" class="tabBody">',
"tab.end" => '</div>',
"tab.sequence" => $tabIdx,
"tab.label" => $tab->{label},
"tab.tid" => $tabId,
"tab.subtext" => $tab->{subtext},
"tab.controls" => $self->_tabAdminIcons($tabId),
"tab.field_loop" => [],
};
push @tabLoop, $tabVars;
$tabById{$tabId} = $tabVars;
}
my @fieldLoop;
my @fields = map { $self->getFieldConfig($_) } @{ $self->getFieldOrder };
for my $field (@fields) {
# need a copy
my $value;
if ($entry) {
$value = $entry->field( $field->{name} );
}
elsif (!$ignoreForm && defined (my $formValue = $self->session->form->process($field->{name}))) {
$value = $formValue;
}
my $hidden
= ($field->{status} eq 'hidden' && !$session->var->isAdminOn)
|| ($field->{isMailField} && !$self->get('mailData'));
# populate Rich Editor field if the field is an HTMLArea
if ($field->{type} eq "HTMLArea") {
$field->{htmlAreaRichEditor} = $self->get("htmlAreaRichEditor") ;
}
my $form = $self->_createForm($field, $value);
$value = $form->getValueAsHtml;
my %fieldProperties = (
"form" => $form->toHtml,
"name" => $field->{name},
"tid" => $field->{tabId},
"value" => $form->getValueAsHtml,
"label" => $field->{label},
"isMailField" => $field->{isMailField},
"isHidden" => $hidden,
"isDisplayed" => ($field->{status} eq "visible" && !$hidden),
"isRequired" => ($field->{status} eq "required" && !$hidden),
"subtext" => $field->{subtext},
"type" => $field->{type},
"controls" => $self->_fieldAdminIcons($field->{name}),
"inTab" => ($field->{tabId} ? 1 : 0),
);
my %fieldLoopEntry;
my %tabLoopEntry;
while (my ($propKey, $propValue) = each %fieldProperties) {
$var->{"field.noloop.$field->{name}.$propKey"} = $propValue;
$fieldLoopEntry{"field.$propKey"} = $propValue;
$tabLoopEntry{"tab.field.$propKey"} = $propValue;
}
push @fieldLoop, \%fieldLoopEntry;
my $tab = $tabById{ $field->{tabId} };
if ($tab) {
push @{ $tab->{'tab.field_loop'} }, \%tabLoopEntry;
}
}
$var->{field_loop} = \@fieldLoop;
$var->{tab_loop} = \@tabLoop;
$var->{'form.send'} = WebGUI::Form::submit($session, { value => $i18n->get(73) });
$var->{'form.save'} = WebGUI::Form::submit($session);
# Create CAPTCHA if configured and user is not a Registered User
if ( $self->useCaptcha ) {
# Create one captcha we can use multiple times
$var->{ 'form_captcha' } = WebGUI::Form::Captcha( $session, {
name => 'captcha',
} );
}
$var->{'form.end'} = WebGUI::Form::formFooter($session);
return $var;
}
#----------------------------------------------------------------------------
=head2 getTemplateVars ( )
Gets the default template vars for the asset. Includes the asset properties
as well as shared template vars.
=cut
sub getTemplateVars {
my $self = shift;
my $var = $self->get;
my $i18n = WebGUI::International->new($self->session,"Asset_DataForm");
$var->{'useCaptcha' } = ( $self->useCaptcha ? 1 : 0 );
$var->{'canEdit' } = ($self->canEdit);
$var->{'canViewEntries' } = ($self->session->user->isInGroup($self->get("groupToViewEntries")));
$var->{'hasEntries' } = $self->hasEntries;
$var->{'entryList.url' } = $self->getListUrl;
$var->{'entryList.label' } = $i18n->get(86);
$var->{'export.tab.url' } = $self->getUrl('func=exportTab');
$var->{'export.tab.label' } = $i18n->get(84);
$var->{'addField.url' } = $self->getUrl('func=editField');
$var->{'addField.label' } = $i18n->get(76);
$var->{'deleteAllEntries.url' } = $self->getUrl("func=deleteAllEntriesConfirm");
$var->{'deleteAllEntries.label' } = $i18n->get(91);
$var->{'javascript.confirmation.deleteAll'}
= sprintf("return confirm('%s');",$i18n->get('confirm delete all'));
$var->{'javascript.confirmation.deleteOne'}
= sprintf("return confirm('%s');",$i18n->get('confirm delete one'));
$var->{'addTab.label' } = $i18n->get(105);;
$var->{'addTab.url' }= $self->getUrl('func=editTab');
$var->{'tab.init' }= $self->_createTabInit($self->getId);
return $var;
}
#-------------------------------------------------------------------
=head2 hasEntries ( )
Returns number of entries that exist for this dataform.
=cut
sub hasEntries {
my $self = shift;
return $self->entryClass->getCount($self);
}
#-------------------------------------------------------------------
=head2 prepareView ( )
See WebGUI::Asset::prepareView() for details.
=cut
sub prepareView {
my $self = shift;
$self->SUPER::prepareView(@_);
my $view = $self->currentView;
if ( $view eq 'form' ) {
$self->prepareViewForm(@_);
}
else {
$self->prepareViewList(@_);
}
}
#-------------------------------------------------------------------
sub purge {
my $self = shift;
$self->deleteAttachedFiles;
$self->entryClass->purgeAssetEntries($self);
return $self->SUPER::purge(@_);
}
#-------------------------------------------------------------------
sub sendEmail {
my $self = shift;
my $var = shift;
my $entry = shift;
my $to = $entry->field('to');
my $subject = $entry->field('subject');
my $from = $entry->field('from');
my $bcc = $entry->field('bcc');
my $cc = $entry->field('cc');
my $message = $self->processTemplate($var, $self->get("emailTemplateId"));
WebGUI::Macro::process($self->session,\$message);
my @attachments = $self->get('mailAttachments')
? @{ $self->getAttachedFiles($entry) }
: ();
if ($to =~ /\@/) {
my $mail = WebGUI::Mail::Send->create($self->session,{
to => $to,
replyTo => $from,
subject => $subject,
cc => $cc,
from => $from,
bcc => $bcc,
});
$mail->addHtml($message);
$mail->addFooter;
$mail->addAttachment($_) for (@attachments);
$mail->queue;
}
else {
my $userId;
my $groupId;
if (my $user = WebGUI::User->newByUsername($self->session, $to)) {
$userId = $user->userId;
}
elsif (my $group = WebGUI::Group->find($self->session, $to)) {
$groupId = $group->getId;
}
else {
$self->session->errorHandler->warn($self->getId . ": Unable to send message, no user or group found.");
return;
}
WebGUI::Inbox->new($self->session)->addMessage({
userId => $userId,
groupId => $groupId,
sentBy => $self->session->user->userId,
subject => $subject,
message => $message,
status => 'unread',
});
if ($cc) {
my $mail = WebGUI::Mail::Send->create($self->session,{to=>$cc, replyTo=>$from, subject=>$subject, from=>$from});
$mail->addHtml($message);
$mail->addAttachment($_) for (@attachments);
$mail->addFooter;
$mail->queue;
}
if ($bcc) {
my $mail = WebGUI::Mail::Send->create($self->session, {to=>$bcc, replyTo=>$from, subject=>$subject, from=>$from});
$mail->addHtml($message);
$mail->addAttachment($_) for (@attachments);
$mail->addFooter;
$mail->queue;
}
}
}
#----------------------------------------------------------------------------
=head2 useCaptcha ( )
Returns true if we should use and process the CAPTCHA.
We should use the CAPTCHA if it is selected in the asset properties and the
user is not a Registered User.
=cut
sub useCaptcha {
my $self = shift;
if ( $self->get('useCaptcha') && $self->session->user->isVisitor ) {
return 1;
}
return 0;
}
#-------------------------------------------------------------------
sub view {
my $self = shift;
my $view = $self->currentView;
if ( $view eq 'form' ) {
return $self->viewForm(@_);
}
else {
return $self->viewList(@_);
}
}
#-------------------------------------------------------------------
sub canView {
my $self = shift;
return 0
if !$self->SUPER::canView;
if ($self->currentView eq 'list') {
return 1
if $self->canEdit;
return 1
if $self->session->user->isInGroup($self->get('groupToViewEntries'));
return 0;
}
return 1;
}
sub prepareViewList {
my $self = shift;
my $templateId = $self->get('listTemplateId');
my $template = WebGUI::Asset::Template->new($self->session, $templateId);
if (!$template) {
WebGUI::Error::ObjectNotFound::Template->throw(
error => qq{Template not found},
templateId => $templateId,
assetId => $self->getId,
);
}
$template->prepare($self->getMetaDataAsTemplateVariables);
$self->{_viewListTemplate} = $template;
}
sub viewList {
my $self = shift;
my $var = $self->getTemplateVars;
return $self->processTemplate($self->getListTemplateVars($var), undef, $self->{_viewListTemplate});
}
sub prepareViewForm {
my $self = shift;
$self->session->style->setLink($self->session->url->extras('tabs/tabs.css'), {"type"=>"text/css"});
$self->session->style->setScript($self->session->url->extras('tabs/tabs.js'), {"type"=>"text/javascript"});
my $templateId = $self->get('templateId');
my $template = WebGUI::Asset::Template->new($self->session, $templateId);
if (!$template) {
WebGUI::Error::ObjectNotFound::Template->throw(
error => qq{Template not found},
templateId => $templateId,
assetId => $self->getId,
);
}
$template->prepare($self->getMetaDataAsTemplateVariables);
$self->{_viewFormTemplate} = $template;
}
#-------------------------------------------------------------------
sub viewForm {
my $self = shift;
my $passedVars = shift;
my $entry = shift;
my $var = $self->getTemplateVars;
if (!$entry) {
my $entryId = $self->session->form->process("entryId");
$entry = $self->entryClass->new($self, ($entryId && $self->canEdit) ? $entryId : ());
}
$var = $passedVars || $self->getRecordTemplateVars($var, $entry);
return $self->processTemplate($var, undef, $self->{_viewFormTemplate});
}
sub entryClass {
return 'WebGUI::AssetCollateral::DataForm::Entry';
}
#-------------------------------------------------------------------
sub www_deleteAllEntriesConfirm {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
$self->deleteAttachedFiles;
$self->entryClass->purgeAssetEntries($self);
$self->{_mode} = 'list';
return $self->www_view;
}
#-------------------------------------------------------------------
#sub www_deleteAttachedFile {
# my $self = shift;
# my $fieldId = $self->session->form->process('fieldId');
# return $self->session->privilege->insufficient() unless ($self->canEdit);
# $self->deleteAttachedFiles($fieldId);
# return $self->www_view;
#}
#-------------------------------------------------------------------
sub www_deleteEntry {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
my $entryId = $self->session->form->process("entryId");
$self->deleteAttachedFiles(entryId => $entryId);
$self->entryClass->new($self, $entryId)->delete;
$self->{_mode} = 'list';
return $self->www_view;
}
#-------------------------------------------------------------------
sub www_deleteFieldConfirm {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
my $newSelf = $self->addRevision;
$newSelf->deleteField($self->session->form->process("fieldName"));
$newSelf->{_mode} = 'form';
WebGUI::VersionTag->autoCommitWorkingIfEnabled($self->session);
return $newSelf->www_view;
}
#-------------------------------------------------------------------
sub www_deleteTabConfirm {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
my $newSelf = $self->addRevision;
$newSelf->deleteTab($self->session->form->process("tabId"));
$newSelf->{_mode} = 'form';
WebGUI::VersionTag->autoCommitWorkingIfEnabled($self->session);
return $newSelf->www_view;
}
#-------------------------------------------------------------------
sub www_editField {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
my $i18n = WebGUI::International->new($self->session,"Asset_DataForm");
my $fieldName = shift || $self->session->form->process("fieldName");
my $field;
undef $fieldName
if $fieldName eq 'new';
if ($fieldName) {
$field = $self->getFieldConfig($fieldName);
}
else {
$field = {};
}
my $f = WebGUI::HTMLForm->new($self->session, action => $self->getUrl);
$f->hidden(
name => "fieldName",
value => $field->{name},
);
$f->hidden(
name => "func",
value => "editFieldSave"
);
$f->text(
name=>"label",
label=>$i18n->get(77),
hoverHelp=>$i18n->get('77 description'),
value=>$field->{label}
);
if ($field->{isMailField}) {
$f->readOnly(
name => "newName",
label => $i18n->get(21),
hoverHelp => $i18n->get('21 description'),
value => $field->{name},
);
}
else {
$f->text(
name => "newName",
label => $i18n->get(21),
hoverHelp => $i18n->get('21 description'),
value => $field->{name},
);
}
tie my %tabs, 'Tie::IxHash';
%tabs = (
0 => $i18n->get("no tab"),
map { $_ => $self->getTabConfig($_)->{label} } @{ $self->getTabOrder },
);
$f->selectBox(
name => "tabId",
options => \%tabs,
label => $i18n->get(104),
hoverHelp => $i18n->get('104 description'),
value => [ $field->{tabId} ]
);
$f->text(
name => "subtext",
value => $field->{subtext},
label => $i18n->get(79),
hoverHelp => $i18n->get('79 description'),
);
tie my %fieldStatus, 'Tie::IxHash';
%fieldStatus = (
"hidden" => $i18n->get(4),
"visible" => $i18n->get(5),
"editable" => $i18n->get(6),
"required" => $i18n->get(75),
);
$f->selectBox(
name => "status",
options => \%fieldStatus,
label => $i18n->get(22),
hoverHelp => $i18n->get('22 description'),
value => [ $field->{status} || "editable" ],
);
$f->fieldType(
name => "type",
label => $i18n->get(23),
hoverHelp => $i18n->get('23 description'),
value => "\u$field->{type}" || "Text",
types => [qw(DateTime TimeField Float Zipcode Text Textarea HTMLArea Url Date Email Phone Integer YesNo SelectList RadioList CheckList SelectBox File)],
);
$f->integer(
name => "width",
label => $i18n->get(8),
hoverHelp => $i18n->get('8 description'),
value => ($field->{width} || 0),
);
$f->integer(
name => "rows",
value => $field->{rows} || 0,
label => $i18n->get(27),
hoverHelp => $i18n->get('27 description'),
subtext => $i18n->get(28),
);
$f->yesNo(
name=>"vertical",
value=>$field->{vertical},
label=>$i18n->get('editField vertical label'),
hoverHelp=>$i18n->get('editField vertical label description'),
subtext=>$i18n->get('editField vertical subtext')
);
$f->text(
name=>"extras",
value=>$field->{extras},
label=>$i18n->get('editField extras label'),
hoverHelp=>$i18n->get('editField extras label description'),
);
$f->textarea(
-name=>"options",
-label=>$i18n->get(24),
-hoverHelp=>$i18n->get('24 description'),
-value=>$field->{options},
-subtext=>'<br />'.$i18n->get(85)
);
$f->textarea(
-name=>"defaultValue",
-label=>$i18n->get(25),
-hoverHelp=>$i18n->get('25 description'),
-value=>$field->{defaultValue},
-subtext=>'<br />'.$i18n->get(85)
);
if (!$fieldName) {
$f->whatNext(
options => {
"editField" => $i18n->get(76),
"viewDataForm" => $i18n->get(745),
},
value => "editField"
);
}
$f->submit;
my $ac = $self->getAdminConsole;
return $ac->render($f->print,$i18n->get('20'));
}
#-------------------------------------------------------------------
sub www_editFieldSave {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient
unless $self->canEdit;
my $form = $session->form;
my $fieldName = $form->process('fieldName');
my $newName = $session->url->urlize($form->process('newName') || $form->process('label'));
$newName =~ tr{-/}{};
# Make sure we don't rename special fields
my $isMailField = 0;
if ($fieldName) {
my $field = $self->getFieldConfig($fieldName);
if ($field->{isMailField}) {
$newName = $fieldName;
$isMailField = 1;
}
}
# Make sure our field name is unique
if (!$fieldName || $fieldName ne $newName) {
my $i = '';
while ($self->getFieldConfig($newName . $i)) {
$i ||= 1;
$i++;
}
$newName .= $i;
}
my %field = (
width => $form->process("width", 'integer'),
label => $form->process("label"),
tabId => $form->process("tabId") || undef,
status => $form->process("status", 'selectBox'),
type => $form->process("type", 'fieldType'),
options => $form->process("options", 'textarea'),
defaultValue => $form->process("defaultValue", 'textarea'),
subtext => $form->process("subtext"),
rows => $form->process("rows", 'integer'),
vertical => $form->process("vertical", 'yesNo'),
extras => $form->process("extras"),
);
if ($isMailField) {
$field{isMailField} = 1;
}
my $newSelf = $self->addRevision;
if ($fieldName) {
if ($fieldName ne $newName) {
$newSelf->renameField($fieldName, $newName);
}
$newSelf->setField($newName, \%field);
}
else {
$newSelf->createField($newName, \%field);
}
if ($form->process("proceed") eq "editField") {
return $newSelf->www_editField('new');
}
$newSelf->{_mode} = 'form';
WebGUI::VersionTag->autoCommitWorkingIfEnabled($self->session);
return $newSelf->www_view;
}
sub createField {
my $self = shift;
my $fieldName = shift;
my $field = shift;
my $copy = { %{ $field }, name => $fieldName };
if ($self->getFieldConfig->{$fieldName}) {
return 0;
}
$self->getFieldConfig->{$fieldName} = $copy;
push @{ $self->getFieldOrder }, $fieldName;
$self->_saveFieldConfig;
return 1;
}
sub setField {
my $self = shift;
my $fieldName = shift;
my $field = shift;
$field->{ name } = $fieldName;
my $fieldConfig = $self->getFieldConfig;
if (!$fieldConfig->{$fieldName}) {
return 0;
}
$fieldConfig->{$fieldName} = $field;
$self->_saveFieldConfig;
return 1;
}
#-------------------------------------------------------------------
sub www_editTab {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
my $i18n = WebGUI::International->new($self->session,"Asset_DataForm");
my $tabId = shift || $self->session->form->process("tabId") || "new";
my $tab;
unless ($tabId eq "new") {
$tab = $self->getTabConfig($tabId);
}
my $f = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl);
$f->hidden(
-name => "tabId",
-value => $tabId,
);
$f->hidden(
-name => "func",
-value => "editTabSave"
);
$f->text(
-name=>"label",
-label=>$i18n->get(101),
-value=>$tab->{label}
);
$f->textarea(
-name=>"subtext",
-label=>$i18n->get(79),
-value=>$tab->{subtext},
-subtext=>""
);
if ($tabId eq "new") {
$f->whatNext(
options=>{
editTab=>$i18n->get(103),
""=>$i18n->get(745)
},
-value=>"editTab"
);
}
$f->submit;
my $ac = $self->getAdminConsole;
return $ac->render($f->print,$i18n->get('103')) if $tabId eq "new";
return $ac->render($f->print,$i18n->get('102'));
}
#-------------------------------------------------------------------
sub www_editTabSave {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
my $name = $self->session->form->process("name") || $self->session->form->process("label");
$name = $self->session->url->urlize($name);
my $tabId = $self->session->form->process('tabId');
undef $tabId
if $tabId eq 'new';
$name =~ tr{-/}{};
my $tab;
if (!$tabId || !($tab = $self->getTabConfig($tabId)) ) {
$tabId = $self->session->id->generate;
$tab = {
tabId => $tabId,
};
$self->getTabConfig->{$tabId} = $tab;
push @{ $self->getTabOrder }, $tabId;
}
$tab->{label} = $self->session->form->process("label");
$tab->{subtext} = $self->session->form->process("subtext", 'textarea');
$self->_saveTabConfig;
if ($self->session->form->process("proceed") eq "editTab") {
return $self->www_editTab("new");
}
$self->{_mode} = 'form';
return "";
}
#-------------------------------------------------------------------
sub www_exportTab {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient
unless $self->canEdit;
my @exportFields;
for my $field ( map { $self->getFieldConfig($_) } @{$self->getFieldOrder} ) {
next
if $field->{isMailField} && !$self->get('mailData');
push @exportFields, $field->{name};
}
my $tsv = Text::CSV_XS->new({sep_char => "\t", eol => "\n", binary => 1});
$tsv->combine(
'entryId',
'ipAddress',
'username',
'userId',
'submissionDate',
@exportFields,
);
$session->http->setFilename($self->get("url").".tab","text/plain");
$session->http->sendHeader;
$session->output->print($tsv->string, 1);
my $entryIter = $self->entryClass->iterateAll($self);
while (my $entry = $entryIter->()) {
my $entryFields = $entry->fields;
$tsv->combine(
$entry->getId,
$entry->ipAddress,
$entry->username,
$entry->userId,
$entry->submissionDate->webguiDate,
@{ $entryFields }{@exportFields},
);
$session->output->print($tsv->string, 1);
}
return 'chunked';
}
#-------------------------------------------------------------------
sub www_moveFieldDown {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
my $newSelf = $self->addRevision;
my $fieldName = $self->session->form->process('fieldName');
$newSelf->moveFieldDown($fieldName);
WebGUI::VersionTag->autoCommitWorkingIfEnabled($self->session);
return $newSelf->www_view;
}
sub moveFieldDown {
my $self = shift;
my $fieldName = shift;
my $fieldOrder = $self->getFieldOrder;
my $currentPos;
for ($currentPos = 0; $currentPos < @$fieldOrder; $currentPos++) {
last
if $fieldName eq $fieldOrder->[$currentPos];
}
my $tabId = $self->getFieldConfig($fieldName)->{tabId};
my $newPos;
for ($newPos = $currentPos + 1; $newPos < @$fieldOrder; $newPos++) {
last
if $tabId eq $self->getFieldConfig($fieldOrder->[$newPos])->{tabId};
}
if ($newPos < @$fieldOrder) {
splice @$fieldOrder, $newPos, 0, splice(@$fieldOrder, $currentPos, 1);
$self->_saveFieldConfig;
}
return 1;
}
#-------------------------------------------------------------------
sub www_moveFieldUp {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
my $newSelf = $self->addRevision;
my $fieldName = $self->session->form->process('fieldName');
$newSelf->moveFieldUp($fieldName);
WebGUI::VersionTag->autoCommitWorkingIfEnabled($self->session);
return $newSelf->www_view;
}
sub moveFieldUp {
my $self = shift;
my $fieldName = shift;
my $fieldOrder = $self->getFieldOrder;
my $currentPos;
for ($currentPos = 0; $currentPos < @$fieldOrder; $currentPos++) {
last
if $fieldName eq $fieldOrder->[$currentPos];
}
my $tabId = $self->getFieldConfig($fieldName)->{tabId};
my $newPos;
for ($newPos = $currentPos - 1; $newPos < 0; $newPos--) {
last
if $tabId eq $self->getFieldConfig($fieldOrder->[$newPos])->{tabId};
}
if ($newPos >= 0) {
splice @$fieldOrder, $newPos, 0, splice(@$fieldOrder, $currentPos, 1);
$self->_saveFieldConfig;
}
return 1;
}
#-------------------------------------------------------------------
sub www_moveTabRight {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
my $newSelf = $self->addRevision;
my $tabId = $self->session->form->process('tabId');
$newSelf->moveTabRight($tabId);
WebGUI::VersionTag->autoCommitWorkingIfEnabled($self->session);
return $newSelf->www_view;
}
sub moveTabRight {
my $self = shift;
my $tabId = shift;
my $tabOrder = $self->getTabOrder;
my $currentPos;
for ($currentPos = 0; $currentPos < @$tabOrder; $currentPos++) {
last
if $tabId eq $tabOrder->[$currentPos];
}
my $newPos = $currentPos + 1;
if ($newPos < @$tabOrder) {
splice @$tabOrder, $newPos, 0, splice(@$tabOrder, $currentPos, 1);
$self->_saveTabConfig;
}
return 1;
}
#-------------------------------------------------------------------
sub www_moveTabLeft {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canEdit;
my $newSelf = $self->addRevision;
my $tabId = $self->session->form->process('tabId');
$newSelf->moveTabLeft($tabId);
WebGUI::VersionTag->autoCommitWorkingIfEnabled($self->session);
return $newSelf->www_view;
}
sub moveTabLeft {
my $self = shift;
my $tabId = shift;
my $tabOrder = $self->getTabOrder;
my $currentPos;
for ($currentPos = 0; $currentPos < @$tabOrder; $currentPos++) {
last
if $tabId eq $tabOrder->[$currentPos];
}
my $newPos = $currentPos - 1;
if ($newPos >= 0) {
splice @$tabOrder, $newPos, 0, splice(@$tabOrder, $currentPos, 1);
$self->_saveTabConfig;
}
return 1;
}
#-------------------------------------------------------------------
sub www_process {
my $self = shift;
return $self->session->privilege->insufficient
unless $self->canView;
my $session = $self->session;
my $i18n = WebGUI::International->new($session,"Asset_DataForm");
my $entryId = $session->form->process('entryId');
my $entry = $self->entryClass->new($self, ( $entryId ? $entryId : () ) );
my $var = $self->getTemplateVars;
# Process form
my (@errors, $updating, $hadErrors);
for my $field (values %{ $self->getFieldConfig }) {
my $default = $field->{defaultValue};
WebGUI::Macro::process($self->session, \$default);
my $value = $entry->field( $field->{name} ) || $default;
# WebGUI::Form::Integer::getValue() returns 0 even if no number is passed in.
# Not really a suitable default if we want to trigger the error message
if ($field->{status} eq "required" || $field->{status} eq "editable") {
# get the raw value (by sending field type as blank)
my $rawValue = $session->form->process($field->{name}, '');
$value = $session->form->process($field->{name}, $field->{type}, undef, {
defaultValue => $default,
value => $value,
});
# this is a hack, but it's better than changing the default getValue() of Integer, which
# could have massive effects downstream in other uses.
if(($field->{type} =~ /integer/i) && defined($rawValue) && ($rawValue eq '') && ($value eq "0")) {
$value = $rawValue;
}
WebGUI::Macro::filter(\$value);
}
if ($field->{status} eq "required" && (! defined($value) || $value =~ /^\s*$/)) {
push @errors, {
"error.message" => $field->{label} . " " . $i18n->get(29) . ".",
};
}
$entry->field($field->{name}, $value);
}
# Process CAPTCHA
if ( $self->useCaptcha && !$session->form->process( 'captcha', 'captcha' ) ) {
push @errors, {
"error.message" => $i18n->get( 'error captcha' ),
};
}
# Prepare template variables
$var = $self->getRecordTemplateVars($var, $entry);
# If errors, show error page
if (@errors) {
$var->{error_loop} = \@errors;
$self->prepareViewForm;
return $self->processStyle($self->viewForm($var, $entry), { noHeadTags => 1 });
}
# Send email
if ($self->get("mailData") && !$entryId) {
$self->sendEmail($var, $entry);
}
# Save entry to database
if ($self->get('storeData')) {
$entry->save;
}
# Run the workflow
if ( $self->get("workflowIdAddEntry") ) {
my $instanceVar = {
workflowId => $self->get( "workflowIdAddEntry" ),
className => "WebGUI::AssetCollateral::DataForm::Entry",
};
# If we've saved the entry, we only need the ID
if ( $self->get( 'storeData' ) ) {
$instanceVar->{ methodName } = "new";
$instanceVar->{ parameters } = $entry->getId;
}
# We haven't saved the entry, we need the whole thing
else {
$instanceVar->{ methodName } = "newFromHash";
$instanceVar->{ parameters } = [ $self->getId, $entry->getHash ];
}
WebGUI::Workflow::Instance->create( $self->session, $instanceVar )->start;
}
return $self->processStyle($self->processTemplate($var,$self->get("acknowlegementTemplateId")))
if $self->defaultViewForm;
return '';
}
1;