Merge commit '41575d24bb' into webgui8. Some tests still failing.

Conflicts:
	docs/gotcha.txt
	lib/WebGUI.pm
	lib/WebGUI/Asset.pm
	lib/WebGUI/Asset/File/GalleryFile/Photo.pm
	lib/WebGUI/Asset/Post.pm
	lib/WebGUI/Asset/Template.pm
	lib/WebGUI/Asset/WikiPage.pm
	lib/WebGUI/Asset/Wobject/WikiMaster.pm
	lib/WebGUI/Cache.pm
	lib/WebGUI/Content/Setup.pm
	lib/WebGUI/Role/Asset/Subscribable.pm
	lib/WebGUI/Shop/Cart.pm
	lib/WebGUI/Shop/Pay.pm
	lib/WebGUI/Shop/PayDriver/ITransact.pm
	sbin/testEnvironment.pl
	t/Asset/WikiPage.t
	t/Shop/PayDriver.t
	t/Shop/PayDriver/ITransact.t
	t/Shop/PayDriver/Ogone.t
	t/Shop/TaxDriver/EU.t
	t/Shop/TaxDriver/Generic.t
	t/Workflow/Activity/RemoveOldCarts.t
	t/lib/WebGUI/Test.pm
This commit is contained in:
Colin Kuskie 2010-06-25 23:25:26 -07:00
commit 5febc0ebbc
258 changed files with 5528 additions and 2230 deletions

View file

@ -96,6 +96,10 @@ override applyConstraints => sub {
my $storage = $self->getStorageLocation;
my $file = $self->filename;
# Adjust orientation based on exif data. Do this before we start to
# generate resolutions so that all images have the correct orientation.
$self->adjustOrientation;
# Make resolutions before fixing image, so that we can get higher quality
# resolutions
$self->makeResolutions;
@ -110,6 +114,60 @@ override applyConstraints => sub {
super();
};
#----------------------------------------------------------------------------
=head2 adjustOrientation ( )
Read orientation information from EXIF data and rotate image if required.
EXIF data is updated to reflect the new orientation of the image.
=cut
sub adjustOrientation {
my $self = shift;
my $storage = $self->getStorageLocation;
# Extract orientation information from EXIF data
my $exifTool = Image::ExifTool->new;
$exifTool->ExtractInfo( $storage->getPath( $self->get('filename') ) );
my $orientation = $exifTool->GetValue('Orientation', 'ValueConv');
# Check whether orientation information is present and transform image if
# required. At the moment we handle only images that need to be rotated by
# (-)90 or 180 deg. Flipping of images is not supported yet.
if ( $orientation ) {
# We are going to update orientation information before the image is
# rotated. Otherwise we would have to re-extract EXIF data due to
# manipulation by Image Magick.
# Update orientation information
$exifTool->SetNewValue( 'Exif:Orientation' => 1, Type => 'ValueConv');
# Set the following options to make this as robust as possible
$exifTool->Options( 'IgnoreMinorErrors', FixBase => '' );
# Write updated exif data to disk
$exifTool->WriteInfo( $storage->getPath( $self->get('filename') ) );
# Log any errors
my $error = $exifTool->GetValue('Error');
$self->session->log->error( "Error on updating exif data: $error" ) if $error;
# Image rotated by 180°
if ( $orientation == 3 || $orientation == 4 ) {
$self->rotate(180);
}
# Image rotated by 90° CCW
elsif ( $orientation == 5 || $orientation == 6 ) {
$self->rotate(90);
}
# Image rotated by 90° CW
elsif ( $orientation == 7 || $orientation == 8 ) {
$self->rotate(-90);
}
}
}
#-------------------------------------------------------------------
=head2 generateThumbnail ( )

View file

@ -54,10 +54,10 @@ property address2 => (
property city => (
tab => "properties",
fieldType => "text",
label => $i18n->get("city label"),
hoverHelp => $i18n->get("city description"),
},
property region => {
label => ["city label", 'Asset_MapPoint'],
hoverHelp => ["city description", 'Asset_MapPoint'],
);
property region => (
tab => "properties",
fieldType => "text",
label => ["state label", 'Asset_MapPoint'],

View file

@ -77,6 +77,8 @@ with 'WebGUI::Role::Asset::AlwaysHidden';
with 'WebGUI::Role::Asset::SetStoragePermissions';
with 'WebGUI::Role::Asset::AutoSynopsis';
use WebGUI::Group;
use WebGUI::HTML;
use WebGUI::HTMLForm;
@ -170,7 +172,7 @@ Extend the master class to make the default group 7.
sub canAdd {
my $class = shift;
my $session = shift;
$class->SUPER::canAdd($session, undef, '7');
$class->next::method($session, undef, '7');
}
#-------------------------------------------------------------------
@ -617,49 +619,6 @@ sub getStorageLocation {
#-------------------------------------------------------------------
=head2 getSynopsisAndContent ($synopsis, $body)
Returns a synopsis taken from the body of the Post, based on either the separator
macro, the first html paragraph, or the first physical line of text as defined by
newlines.
Returns both the synopsis, and the original body content.
=head3 $synopsis
If passed in, it returns that instead of the calculated synopsis.
=head3 $body
Body of the Post to use a source for the synopsis.
=cut
sub getSynopsisAndContent {
my $self = shift;
my $synopsis = shift;
my $body = shift;
unless ($synopsis) {
my @content;
if( $body =~ /\^\-\;/ ) {
my @pieces = WebGUI::HTML::splitSeparator($body);
$content[0] = shift @pieces;
$content[1] = join '', @pieces;
}
elsif( $body =~ /<p>/ ) {
@content = WebGUI::HTML::splitTag($body);
}
else {
@content = split("\n",$body);
}
shift @content if $content[0] =~ /^\s*$/;
$synopsis = WebGUI::HTML::filter($content[0],"all");
}
return ($synopsis,$body);
}
#-------------------------------------------------------------------
=head2 getTemplateMetadataVars ( $var )
Append metadata as template variables.
@ -1352,6 +1311,7 @@ override trash => sub {
}
};
#-------------------------------------------------------------------
=head2 prepareView
@ -1362,7 +1322,7 @@ Extend the base method to also prepare the Thread containing this Post.
sub prepareView {
my $self = shift;
$self->SUPER::prepareView;
$self->next::method;
unless ($self->getThread->getId eq $self->getId) {
# Need the unless to avoid infinite recursion.
$self->getThread->prepareView;

View file

@ -95,11 +95,9 @@ sub _karma_noFormPost {
use WebGUI::Asset::Template;
use WebGUI::Form;
use WebGUI::Storage;
use WebGUI::Shop::Pay;
use WebGUI::AssetCollateral::Sku::Ad::Ad;
use WebGUI::AdSpace;
use WebGUI::AdSpace::Ad;
use Data::Dumper;
=head1 NAME

View file

@ -383,7 +383,7 @@ sub view {
;
# instanciate address
my $address = WebGUI::Shop::AddressBook->newBySession($self->session)->getAddress($form->get("addressId")) if ($form->get("addressId"));
my $address = WebGUI::Shop::AddressBook->newByUserId($self->session)->getAddress($form->get("addressId")) if ($form->get("addressId"));
# build the form that the user needs to fill out with badge holder information
$vars{formHeader} = WebGUI::Form::formHeader($session, {action => $self->getUrl})

View file

@ -97,6 +97,12 @@ property usePacked => (
hoverHelp => ['usePacked description', 'Asset_Template'],
);
property storageIdExample => (
fieldType => 'image',
label => ['field storageIdExample', 'Asset_Template'],
hoverHelp => ['field storageIdExample description', 'Asset_Template'],
);
use WebGUI::International;
use WebGUI::Asset::Template::HTMLTemplate;
use WebGUI::Utility;
@ -202,6 +208,10 @@ override duplicate => sub {
my $newTemplate = super();
$newTemplate->update({isDefault => 0});
$newTemplate->addAttachments($self->getAttachments);
if ( my $storageId = $self->get('storageIdExample') ) {
my $newStorage = WebGUI::Storage->get( $self->session, $storageId )->copy;
$newTemplate->update({ storageIdExample => $newStorage->getId });
}
return $newTemplate;
};
@ -217,6 +227,9 @@ override exportAssetData => sub {
my ( $self ) = @_;
my $data = super();
$data->{template_attachments} = $self->getAttachments;
if ( $self->get('storageIdExample') ) {
push @{$data->{storage}}, $self->get('storageIdExample');
}
return $data;
};
@ -399,9 +412,32 @@ override getEditForm => sub {
$label = $i18n->get('attachment add field label');
$properties->raw("<tr><td>$label</td><td>$table</td></tr>");
$properties->image(
name => 'storageIdExample',
value => $self->getValue('storageIdExample'),
label => $i18n->get('field storageIdExample'),
hoverHelp => $i18n->get('field storageIdExample description'),
);
return $tabform;
};
#-------------------------------------------------------------------
=head2 getExampleImageUrl ( )
Get the URL to the example image of this template, if any
=cut
sub getExampleImageUrl {
my ( $self ) = @_;
if ( my $storageId = $self->get('storageIdExample') ) {
my $storage = WebGUI::Storage->get( $self->session, $storageId );
return $storage->getUrl( $storage->getFiles->[0] );
}
return;
}
#-------------------------------------------------------------------

View file

@ -54,6 +54,7 @@ property isFeatured => (
with 'WebGUI::Role::Asset::AlwaysHidden';
with 'WebGUI::Role::Asset::Subscribable';
with 'WebGUI::Role::Asset::Comments';
with 'WebGUI::Role::Asset::AutoSynopsis';
use WebGUI::International;
@ -274,35 +275,11 @@ sub getTemplateVars {
$self->scrubContent,
{skipTitles => [$self->title]},
),
isKeywordPage => $self->isKeywordPage,
isSubscribed => $self->isSubscribed,
subscribeUrl => $self->getSubscribeUrl,
unsubscribeUrl => $self->getUnsubscribeUrl,
owner => $owner->get('alias'),
};
my @keyword_pages = ();
if ($var->{isKeywordPage}) {
my $paginator = $keyObj->getMatchingAssets({
startAsset => $self->getWiki,
keyword => $self->get('title'),
usePaginator => 1,
});
PAGE: foreach my $assetId (@{ $paginator->getPageData }) {
next PAGE if $assetId->{assetId} eq $self->getId;
my $asset = eval { WebGUI::Asset->newById($session, $assetId->{assetId}); };
next PAGE if Exception::Class->caught();
push @keyword_pages, {
title => $asset->getTitle,
url => $asset->getUrl,
};
}
$paginator->appendTemplateVars($var);
@keyword_pages = map { $_->[1] }
sort
map { [ lc $_->{title}, $_ ] }
@keyword_pages;
}
$var->{keyword_page_loop} = \@keyword_pages;
return $var;
}
@ -340,24 +317,6 @@ around indexContent => sub {
#-------------------------------------------------------------------
=head2 isKeywordPage
Returns a boolean indicating whether or not the name of this WikiPage matches any keyword in the Wiki that
contains it.
=cut
sub isKeywordPage {
my $self = shift;
my $keywords = WebGUI::Keyword->new($self->session)->getMatchingAssets({
asset => $self->getWiki,
keyword => $self->get('title'),
});
return scalar @{ $keywords };
}
#-------------------------------------------------------------------
=head2 preparePageTemplate
This is essentially prepareView, but is smart and will only do the template
@ -415,6 +374,8 @@ sub processPropertiesFromFormPost {
$properties->{isFeatured} = $session->form->get("isFeatured");
}
($properties->{synopsis}) = $self->getSynopsisAndContent(undef, $self->get('content'));
$self->update($properties);
# deal with attachments from the attachments form control
@ -468,7 +429,8 @@ sub scrubContent {
my $self = shift;
my $content = shift || $self->content;
my $scrubbedContent = WebGUI::HTML::filter($content, $self->getWiki->filterCode);
$content =~ s/\^-\;//g;
my $scrubbedContent = WebGUI::HTML::filter($content, $self->getWiki->get("filterCode"));
if ($self->getWiki->useContentFilter) {
$scrubbedContent = WebGUI::HTML::processReplacements($self->session, $scrubbedContent);

View file

@ -181,6 +181,14 @@ property filterCode => (
label => ['filter code', 'Asset_WikiMaster'],
hoverHelp => ['filter code description', 'Asset_WikiMaster'],
);
property topLevelKeywords => (
fieldType => "keywords",
default => '',
tab => 'properties',
label => ['top level keywords', 'Asset_WikiMaster'],
hoverHelp => ['top level keywords description', 'Asset_WikiMaster'],
);
with 'WebGUI::Role::Asset::Subscribable';
with 'WebGUI::Role::Asset::RssFeed';
@ -213,13 +221,12 @@ sub appendFeaturedPageVars {
=head2 appendKeywordPageVars ( var )
Append the template variables to C<var> for keyword (catagory) pages.
Append the template variables to C<var> for keyword (category) pages.
=cut
sub appendKeywordPageVars {
my ( $self, $var ) = @_;
my $session = $self->session;
my $topKeywords = $self->getTopLevelKeywordsList;
my $keywordHierarchy = $self->getKeywordHierarchy( $topKeywords, );
$var->{keywords_loop} = $self->getKeywordVariables( $keywordHierarchy );
@ -228,6 +235,7 @@ sub appendKeywordPageVars {
#-------------------------------------------------------------------
=head2 appendMostPopular ($var, [ $limit ])
=head3 $var
@ -242,10 +250,10 @@ If passed in, this will override the mostPopularCount set in the object.
=cut
sub appendMostPopular {
my $self = shift;
my $var = shift;
my $limit = shift || $self->mostPopularCount;
foreach my $asset (@{$self->getLineage(["children"],{returnObjects=>1, limit=>$limit, includeOnlyClasses=>["WebGUI::Asset::WikiPage"]})}) {
my $self = shift;
my $var = shift;
my $limit = shift || $self->get("mostPopularCount");
foreach my $asset (@{$self->getLineage(["children"],{returnObjects=>1, limit=>$limit, includeOnlyClasses=>["WebGUI::Asset::WikiPage"], joinClass => 'WebGUI::Asset::WikiPage', orderByClause => 'WikiPage.views DESC'})}) {
if (defined $asset) {
push(@{$var->{mostPopular}}, {
title=>$asset->getTitle,
@ -461,177 +469,20 @@ sub canEditPages {
}
#-------------------------------------------------------------------
sub definition {
my $class = shift;
my $session = shift;
my $definition = shift;
my $i18n = WebGUI::International->new($session, 'Asset_WikiMaster');
my %properties;
tie %properties, 'Tie::IxHash';
%properties =
(
groupToEditPages => { fieldType => 'group',
defaultValue => ['2'],
tab => 'security',
hoverHelp => $i18n->get('groupToEditPages hoverHelp'),
label => $i18n->get('groupToEditPages label') },
=head2 deleteSubKeywords ( $keyword )
groupToAdminister => { fieldType => 'group',
defaultValue => ['3'],
tab => 'security',
hoverHelp => $i18n->get('groupToAdminister hoverHelp'),
label => $i18n->get('groupToAdminister label') },
Delete all keywords that are associated with a particular keyword for this wiki.
richEditor => { fieldType => 'selectRichEditor',
defaultValue => 'PBrichedit000000000001',
tab => 'display',
hoverHelp => $i18n->get('richEditor hoverHelp'),
label => $i18n->get('richEditor label') },
=head3 $keyword
frontPageTemplateId => { fieldType => 'template',
namespace => 'WikiMaster_front',
defaultValue => 'WikiFrontTmpl000000001',
tab => 'display',
hoverHelp => $i18n->get('frontPageTemplateId hoverHelp'),
label => $i18n->get('frontPageTemplateId label') },
The main keyword to key off of.
pageTemplateId => { fieldType => 'template',
namespace => 'WikiPage',
defaultValue => 'WikiPageTmpl0000000001',
tab => 'display',
hoverHelp => $i18n->get('pageTemplateId hoverHelp'),
label => $i18n->get('pageTemplateId label') },
=cut
pageHistoryTemplateId => { fieldType => 'template',
namespace => 'WikiPage_pageHistory',
defaultValue => 'WikiPHTmpl000000000001',
tab => 'display',
hoverHelp => $i18n->get('pageHistoryTemplateId hoverHelp'),
label => $i18n->get('pageHistoryTemplateId label') },
mostPopularTemplateId => { fieldType => 'template',
namespace => 'WikiMaster_mostPopular',
defaultValue => 'WikiMPTmpl000000000001',
tab => 'display',
hoverHelp => $i18n->get('mostPopularTemplateId hoverHelp'),
label => $i18n->get('mostPopularTemplateId label') },
recentChangesTemplateId => { fieldType => 'template',
namespace => 'WikiMaster_recentChanges',
defaultValue => 'WikiRCTmpl000000000001',
tab => 'display',
hoverHelp => $i18n->get('recentChangesTemplateId hoverHelp'),
label => $i18n->get('recentChangesTemplateId label') },
byKeywordTemplateId => { fieldType => 'template',
namespace => 'WikiMaster_byKeyword',
defaultValue => 'WikiKeyword00000000001',
tab => 'display',
hoverHelp => $i18n->get('byKeywordTemplateId hoverHelp'),
label => $i18n->get('byKeywordTemplateId label') },
searchTemplateId => { fieldType => 'template',
namespace => 'WikiMaster_search',
defaultValue => 'WikiSearchTmpl00000001',
tab => 'display',
hoverHelp => $i18n->get('searchTemplateId hoverHelp'),
label => $i18n->get('searchTemplateId label') },
pageEditTemplateId => { fieldType => 'template',
namespace => 'WikiPage_edit',
defaultValue => 'WikiPageEditTmpl000001',
tab => 'display',
hoverHelp => $i18n->get('pageEditTemplateId hoverHelp'),
label => $i18n->get('pageEditTemplateId label') },
recentChangesCount => { fieldType => 'integer',
defaultValue => 50,
tab => 'display',
hoverHelp => $i18n->get('recentChangesCount hoverHelp'),
label => $i18n->get('recentChangesCount label') },
recentChangesCountFront => { fieldType => 'integer',
defaultValue => 10,
tab => 'display',
hoverHelp => $i18n->get('recentChangesCountFront hoverHelp'),
label => $i18n->get('recentChangesCountFront label') },
mostPopularCount => { fieldType => 'integer',
defaultValue => 50,
tab => 'display',
hoverHelp => $i18n->get('mostPopularCount hoverHelp'),
label => $i18n->get('mostPopularCount label') },
mostPopularCountFront => { fieldType => 'integer',
defaultValue => 10,
tab => 'display',
hoverHelp => $i18n->get('mostPopularCountFront hoverHelp'),
label => $i18n->get('mostPopularCountFront label') },
approvalWorkflow =>{
fieldType=>"workflow",
defaultValue=>"pbworkflow000000000003",
type=>'WebGUI::VersionTag',
tab=>'security',
label=>$i18n->get('approval workflow'),
hoverHelp=>$i18n->get('approval workflow description'),
},
thumbnailSize => {
fieldType => "integer",
defaultValue => 0,
tab => "display",
label => $i18n->get("thumbnail size"),
hoverHelp => $i18n->get("thumbnail size help")
},
maxImageSize => {
fieldType => "integer",
defaultValue => 0,
tab => "display",
label => $i18n->get("max image size"),
hoverHelp => $i18n->get("max image size help")
},
allowAttachments => {
fieldType => "integer",
defaultValue => 0,
tab => "security",
label => $i18n->get("allow attachments"),
hoverHelp => $i18n->get("allow attachments help"),
},
useContentFilter =>{
fieldType=>"yesNo",
defaultValue=>1,
tab=>'display',
label=>$i18n->get('content filter'),
hoverHelp=>$i18n->get('content filter description'),
},
filterCode =>{
fieldType=>"filterContent",
defaultValue=>'javascript',
tab=>'security',
label=>$i18n->get('filter code'),
hoverHelp=>$i18n->get('filter code description'),
},
topLevelKeywords =>{
fieldType => "keywords",
defaultValue => '',
tab => 'properties',
label => $i18n->get('top level keywords'),
hoverHelp => $i18n->get('top level keywords description'),
},
);
push @$definition,
{
assetName => $i18n->get('assetName'),
icon => 'wikiMaster.gif',
autoGenerateForms => 1,
tableName => 'WikiMaster',
className => 'WebGUI::Asset::Wobject::WikiMaster',
properties => \%properties,
};
return $class->next::method($session, $definition);
>>>>>>> 808a866c8b2a426e4958d38c34e8753a8555fc90
sub deleteSubKeywords {
my ( $self, $keyword ) = @_;
return $self->session->db->write('delete from WikiMasterKeywords where assetId=? and keyword=?', [$self->getId, $keyword]);
}
#-------------------------------------------------------------------
@ -664,14 +515,15 @@ The hierarchy data structure that looks like this:
[
{
title => 'title', # same as the keyword, since this is a keyword (category) page
url => 'url', # url from the keyword page, via getUrl so it contains the gateway URL
# If a keyword page does not exist for the keyword, this key/value pair will not be present.
children => [ # Array reference of sub-categories referenced by this category
{ # If there are no children, this key/value pair will not be present
keyword => 'keyword', # same as the keyword, since this is a keyword (category) page
url => 'url', # url from the keyword page, via getUrl so it contains the gateway URL
children => [ # Array reference of sub-categories referenced by this category
{ # If there are no children, this key/value pair will not be present
...
}
]
],
descendants => 25, # The total number of wiki pages that this keyword, and any other sub-keywords
# of this keyword, refer to.
}
]
@ -693,25 +545,21 @@ sub getKeywordHierarchy {
my $hierarchy = [];
$keywords ||= $self->getTopLevelKeywordsList;
$seen ||= {};
my $assetKeyword = WebGUI::Keyword->new($session);
KEYWORD: foreach my $keyword (sort @{ $keywords }) {
my $page = $self->getLineage(['children'], {
returnObjects => 1,
whereClause => 'assetData.title = '.$session->db->quote($keyword),
limit => 1,
includeOnlyClasses => [qw/WebGUI::Asset::WikiPage/],
})->[0];
if (! $page) {
push @{ $hierarchy }, { title => $keyword, url => '', };
next KEYWORD;
}
my $datum = {
title => $keyword, ##Note, same as keyword
url => $page->getUrl,
title => $keyword, ##Note, same as keyword
url => $self->getUrl('func=byKeyword;keyword='.$keyword),
descendants => scalar @{ $assetKeyword->getMatchingAssets( { startAsset => $self, keyword => $keyword, }) },
};
##Prevent recursion if seen again
if (! $seen->{$keyword}++) {
my $children = $self->getKeywordHierarchy(WebGUI::Keyword::string2list($page->get('keywords')), $seen, );
##Replace this with a call to getSubKeywords.
my $children = $self->getKeywordHierarchy($self->getSubKeywords($keyword), $seen, );
if (@{ $children } ) {
foreach my $child (@{ $children }) {
$datum->{descendants} += $child->{descendants};
}
$datum->{children} = $children;
}
}
@ -722,6 +570,26 @@ sub getKeywordHierarchy {
#-------------------------------------------------------------------
=head2 getSubKeywords ( $keyword )
Return all keywords that are associated with a particular keyword for this wiki.
=head3 $keyword
The main keyword to key off of.
=cut
sub getSubKeywords {
my ( $self, $keyword ) = @_;
return $self->session->db->buildArrayRef(
'select subKeyword from WikiMasterKeywords where assetId=? and keyword=?',
[$self->getId, $keyword]
);
}
#-------------------------------------------------------------------
=head2 getKeywordVariables ( $hierarchy, $level )
Take a data structure representing a hierarchy of keywords, and append template variables
@ -745,6 +613,7 @@ sub getKeywordVariables {
KEYWORD: foreach my $member (@{ $hierarchy }) {
my $varBlock = clone $member;
$varBlock->{level} = $level;
$varBlock->{isTopLevel} = $level == 0;
$varBlock->{indent_loop} = [ map { { indent => $_ } } 1..$level ];
delete $varBlock->{children};
push @{$variables}, $varBlock;
@ -877,6 +746,48 @@ sub processPropertiesFromFormPost {
#-------------------------------------------------------------------
=head2 purge
Extend the master method to delete all keyword entries.
=cut
sub purge {
my $self = shift;
$self->session->db->write('delete from WikiMasterKeywords where assetId=?',[$self->getId]);
return $self->SUPER::purge;
}
#-------------------------------------------------------------------
=head2 setSubKeywords ( $keyword, @keywords )
Store the set of keywords for this WikiMaster in the db. Returns true.
=head3 $keyword
The keyword that gets the new keywords.
=head3 @keywords
The new set of keywords.
=cut
sub setSubKeywords {
my ( $self, $keyword, @subKeywords ) = @_;
$self->deleteSubKeywords($keyword);
my $stuffIt = $self->session->db->prepare('insert into WikiMasterKeywords (assetId, keyword, subKeyword) values (?,?,?)');
KEYWORD: foreach my $subKeyword (@subKeywords) {
next unless $keyword;
$stuffIt->execute([$self->getId, $keyword, $subKeyword]);
}
$stuffIt->finish;
return 1;
}
#-------------------------------------------------------------------
=head2 shouldSkipNotification ( )
WikiMasters do not send notification
@ -933,30 +844,55 @@ Return search results that match the keyword from the form variable C<keyword>.
=cut
sub www_byKeyword {
my $self = shift;
my $keyword = $self->session->form->process("keyword");
my @pages = ();
my $p = WebGUI::Keyword->new($self->session)->getMatchingAssets({
my $self = shift;
my $session = $self->session;
my $keyword = $session->form->process("keyword");
my $p = WebGUI::Keyword->new($session)->getMatchingAssets({
startAsset => $self,
keyword => $keyword,
usePaginator => 1,
});
});
$p->setBaseUrl($self->getUrl("func=byKeyword;keyword=".$keyword));
my @pages = ();
foreach my $assetData (@{$p->getPageData}) {
my $asset = WebGUI::Asset->newById($self->session, $assetData->{assetId});
next unless defined $asset;
push(@pages, {
title => $asset->getTitle,
url => $asset->getUrl,
title => $asset->getTitle,
url => $asset->getUrl,
synopsis => $asset->get('synopsis'),
});
}
@pages = sort { lc($a->{title}) cmp lc($b->{title}) } @pages;
my $var = {
keyword => $keyword,
pagesLoop => \@pages,
};
keyword => $keyword,
pagesLoop => \@pages,
canAdminister => $self->canAdminister,
recentChangesUrl => $self->getUrl("func=recentChanges"),
mostPopularUrl => $self->getUrl("func=mostPopular"),
wikiHomeUrl => $self->getUrl,
};
$p->appendTemplateVars($var);
return $self->processStyle($self->processTemplate($var, $self->byKeywordTemplateId));
my $subKeywords = $self->getSubKeywords($keyword);
my $keywordHierarchy = $self->getKeywordHierarchy($subKeywords);
$var->{keywords_loop} = $self->getKeywordVariables($keywordHierarchy);
if ($var->{canAdminister}) {
$var->{formHeader} = WebGUI::Form::formHeader($session, {action => $self->getUrl})
. WebGUI::Form::hidden($session, { name => 'func', value => 'subKeywordSave',})
. WebGUI::Form::hidden($session, { name => 'keyword', value => $keyword,});
my $subKeywords = join ', ', @{ $self->getSubKeywords($keyword) };
$var->{keywordForm} = WebGUI::Form::keywords($session, {
name => 'subKeywords',
value => $session->form->get('subKeywords') || $subKeywords,
});
$var->{submitForm} = WebGUI::Form::submit($session, {});
$var->{formFooter} = WebGUI::Form::formFooter($session);
}
return $self->processStyle($self->processTemplate($var, $self->get('byKeywordTemplateId')));
}
@ -1061,5 +997,25 @@ sub www_search {
return $self->processStyle($self->processTemplate($var, $self->searchTemplateId));
}
#-------------------------------------------------------------------
=head2 www_subKeywordSave
Process the form from www_byKeyword and update the subkeywords for a keyword in this wiki.
=cut
sub www_subKeywordSave {
my $self = shift;
my $form = $self->session->form;
my $subKeywords = $form->process('subKeywords', 'keywords');
my $keyword = $form->process('keyword');
my @subKeywords = @{ WebGUI::Keyword::string2list($subKeywords) };
$self->setSubKeywords($keyword, @subKeywords);
return $self->www_byKeyword;
}
__PACKAGE__->meta->make_immutable;
1;

151
lib/WebGUI/Cache/CHI.pm Normal file
View file

@ -0,0 +1,151 @@
package WebGUI::Cache::CHI;
use strict;
use base 'WebGUI::Cache';
use File::Temp qw/tempdir/;
use CHI;
=head1 NAME
WebGUI::Cache::CHI - CHI cache driver
=head1 DESCRIPTION
This is a WebGUI Cache driver to the CHI cache interface. This allows WebGUI
sites to use any CHI::Driver like FastMmap and Memcached
=head1 METHODS
=cut
#----------------------------------------------------------------------------
=head2 delete ( )
Delete the current key
=cut
sub delete {
my ( $self ) = @_;
return $self->{_chi}->remove( $self->{_key} );
}
#----------------------------------------------------------------------------
=head2 deleteChunk ( partialKey )
Delete multiple keys from the cache
=cut
sub deleteChunk {
my ( $self, $key ) = @_;
$key = $self->parseKey( $key );
for my $checkKey ( $self->{_chi}->get_keys ) {
if ( $checkKey =~ /^\Q$key/ ) {
$self->{_chi}->remove( $checkKey );
}
}
}
#----------------------------------------------------------------------------
=head2 flush ( )
Delete the entire cache namespace
=cut
sub flush {
my ( $self ) = @_;
$self->{_chi}->purge;
}
#----------------------------------------------------------------------------
=head2 get ( )
Get the data in the current key
=cut
sub get {
my ( $self ) = @_;
return $self->{_chi}->get( $self->{_key} );
}
#----------------------------------------------------------------------------
=head2 new ( session, key [, namespace] )
Create a new WebGUI::Cache object with the given key. The namespace defaults
to the current site's configuration file name
=cut
sub new {
my ( $class, $session, $key, $namespace ) = @_;
$namespace ||= $session->config->getFilename;
$key = $class->parseKey( $key );
# Create CHI object from config
my $chi;
unless ( $chi = $session->stow->get( "CHI" ) ) {
my $cacheConf = $session->config->get('cache');
$cacheConf->{namespace} = $namespace;
# Default values
my $resolveConf = sub {
my ($config) = @_;
if ( $config->{driver} =~ /DBI/ ) {
$config->{ dbh } = $session->db->dbh;
}
if ( $config->{driver} =~ /File|FastMmap|BerkeleyDB/ ) {
$config->{ root_dir } ||= tempdir();
}
};
$resolveConf->( $cacheConf );
if ( $cacheConf->{l1_cache} ) {
$resolveConf->( $cacheConf->{l1_cache} );
}
$chi = CHI->new( %{$cacheConf} );
$session->stow->set( "CHI", $chi );
}
return bless { _session => $session, _key => $key, _chi => $chi }, $class;
}
#----------------------------------------------------------------------------
=head2 set ( content [, ttl ] )
Set the content to the current key. ttl is the number of seconds the cache
should live.
=cut
sub set {
my ( $self, $content, $ttl ) = @_;
$ttl ||= 60;
$self->{_chi}->set( $self->{_key}, $content, $ttl );
return;
}
#----------------------------------------------------------------------------
=head2 stats ( )
Get the size of the cache
=cut
sub stats {
my ( $self ) = @_;
return $self->{_chi}->get_size;
}
1;

View file

@ -15,13 +15,7 @@ package WebGUI::Content::Setup;
=cut
use strict;
use Digest::MD5;
use WebGUI::Asset;
use WebGUI::HTMLForm;
use WebGUI::International;
use WebGUI::Storage;
use WebGUI::VersionTag;
use WebGUI::Operation::Statistics;
use WebGUI::Wizard::Setup;
=head1 NAME
@ -42,61 +36,6 @@ These subroutines are available from this package:
=cut
#-------------------------------------------------------------------
=head2 addAsset ( parent, properties )
A helper to add assets with less code.
=head3 parent
The parent asset to add to.
=head3 properties
A hash ref of properties to attach to the asset. One must be className.
=cut
sub addAsset {
my $parent = shift;
my $properties = shift;
$properties->{url} = $parent->get("url")."/".$properties->{title};
$properties->{groupIdEdit} = $parent->get("groupIdEdit");
$properties->{groupIdView} = $parent->get("groupIdView");
$properties->{ownerUserId} = $parent->get("ownerUserId");
$properties->{styleTemplateId} = $parent->get("styleTemplateId");
$properties->{printableStyleTemplateId} = $parent->get("styleTemplateId");
return $parent->addChild($properties);
}
#-------------------------------------------------------------------
=head2 addPage ( parent, title )
Adds a page to a parent page.
=head3 parent
A parent page asset.
=head3 title
The title of the new page.
=cut
sub addPage {
my $parent = shift;
my $title = shift;
return addAsset($parent, {title=>$title, className => "WebGUI::Asset::Wobject::Layout", displayTitle=>0});
}
#-------------------------------------------------------------------
=head2 handler ( session )
@ -110,493 +49,16 @@ The current WebGUI::Session object.
=cut
sub handler {
my $session = shift;
my $session = shift;
my $form = $session->form;
unless ($session->setting->get("specialState") eq "init") {
unless ( $session->setting->get("specialState") eq "init" ) {
return undef;
}
$session->http->setCacheControl("none");
my $i18n = WebGUI::International->new($session, "WebGUI");
my ($output,$legend) = "";
if ($form->process("step") eq "2") {
$legend = $i18n->get('company information');
my $timezone = $form->timeZone("timeZone");
my $language = $form->selectBox("language");
##update Admin and Visitor users
my $u = WebGUI::User->new($session,"3");
$u->username($form->process("username","text","Admin"));
$u->profileField("email",$form->email("email"));
$u->profileField("timeZone",$timezone);
$u->profileField("language",$language);
$u->identifier(Digest::MD5::md5_base64($form->process("identifier","password","123qwe")));
$u = WebGUI::User->new($session,"1");
$u->profileField("timeZone",$timezone);
$u->profileField("language",$language);
##update ProfileField defaults so new users the get the defaults, too
my $properties;
my $zoneField = WebGUI::ProfileField->new($session, 'timeZone');
$properties = $zoneField->get();
$properties->{dataDefault} = $timezone;
$zoneField->set($properties);
my $languageField = WebGUI::ProfileField->new($session, 'language');
$properties = $languageField->get();
$properties->{dataDefault} = $language;
$languageField->set($properties);
my $f = WebGUI::HTMLForm->new($session,action=>$session->url->gateway());
$f->hidden( name=>"step", value=>"3");
$f->text(
name=>"companyName",
value=>$session->setting->get("companyName"),
label=>$i18n->get(125),
hoverHelp=>$i18n->get('125 description'),
);
$f->email(
name=>"companyEmail",
value=>$session->setting->get("companyEmail"),
label=>$i18n->get(126),
hoverHelp=>$i18n->get('126 description'),
);
$f->url(
name=>"companyURL",
value=>$session->setting->get("companyURL"),
label=>$i18n->get(127),
hoverHelp=>$i18n->get('127 description'),
);
$f->submit;
$output .= $f->print;
}
elsif ($session->form->process("step") eq "3") {
my $form = $session->form;
$session->setting->set('companyName',$form->text("companyName")) if ($form->get("companyName"));
$session->setting->set('companyURL',$form->url("companyURL")) if ($form->get("companyURL"));
$session->setting->set('companyEmail',$form->email("companyEmail")) if ($form->get("companyEmail"));
$legend = $i18n->get('topicName','Activity_SendWebguiStats');
$output .= ' <p>'.$i18n->get('why to send','Activity_SendWebguiStats').'</p>
<p>'.$i18n->get('would you participate','Activity_SendWebguiStats').'</p>
<p><a href="'.$session->url->gateway(undef, "step=sitestarter").'">'.$i18n->get('disable','Activity_SendWebguiStats').'</a> &nbsp; &nbsp; &nbsp;
<a href="'.$session->url->gateway(undef,"step=sitestarter;enableStats=1").'">'.$i18n->get('enable','Activity_SendWebguiStats').'</a></p>
';
}
elsif ($session->form->process("step") eq "sitestarter") {
my $form = $session->form;
WebGUI::Operation::Statistics::www_enableSendWebguiStats($session) if ($form->get("enableStats"));
$legend = $i18n->get('site starter title');
$output .= ' <p>'.$i18n->get('site starter body').'</p>
<p><a href="'.$session->url->gateway(undef, "step=7").'">'.$i18n->get('no thanks').'</a> &nbsp; &nbsp; &nbsp;
<a href="'.$session->url->gateway(undef,"step=4").'">'.$i18n->get('yes please').'</a></p>
';
}
elsif ($session->form->process("step") eq "4") {
my $f = WebGUI::HTMLForm->new($session,action=>$session->url->gateway());
$f->hidden( name=>"step", value=>"5",);
$f->file(name=>"logo", label=>$i18n->get('logo'));
$f->submit;
$legend = $i18n->get('upload logo');
$output .= $f->print;
}
elsif ($session->form->process("step") eq "5") {
my $storageId = $session->form->process("logo","image");
my $url = $session->url;
my $logoUrl = $url->extras("plainblack.gif");
if (defined $storageId) {
my $storage = WebGUI::Storage->get($session, $storageId);
my $importNode = WebGUI::Asset->getImportNode($session);
my $logo = addAsset($importNode, {
title => $storage->getFiles->[0],
filename => $storage->getFiles->[0],
isHidden => 1,
storageId => $storageId,
className => "WebGUI::Asset::File::Image",
parameters => 'alt="'.$storage->getFiles->[0].'"'
});
$logoUrl = $logo->getStorageLocation->getUrl($logo->get("filename"));
}
my $style = $session->style;
$style->setLink($url->extras('/yui/build/container/assets/skins/sam/container.css'),{ type=>'text/css', rel=>"stylesheet" });
$style->setLink($url->extras('/yui/build/colorpicker/assets/skins/sam/colorpicker.css'),{ type=>'text/css', rel=>"stylesheet" });
$style->setScript($url->extras('/yui/build/yahoo/yahoo-min.js'));
$style->setScript($url->extras('/yui/build/event/event-min.js'));
$style->setScript($url->extras('/yui/build/dom/dom-min.js'));
$style->setScript($url->extras('/yui/build/dragdrop/dragdrop-min.js'));
$style->setScript($url->extras('/yui/build/utilities/utilities.js'));
$style->setScript($url->extras('/yui/build/container/container-min.js'));
$style->setScript($url->extras('/yui/build/slider/slider-min.js'));
$style->setScript($url->extras('/yui/build/colorpicker/colorpicker-min.js'));
$style->setLink($url->extras('/colorpicker/colorpicker.css'),{ type=>'text/css', rel=>"stylesheet" });
$style->setScript($url->extras('/colorpicker/colorpicker.js'));
$style->setScript($url->extras("/styleDesigner/styleDesigner.js"));
$style->setLink($url->extras("/styleDesigner/styleDesigner.css"), {rel=>"stylesheet", type=>"text/css"});
$legend = $i18n->get("style designer");
$output .= '
<form method="post">
<input type="submit" value="'.$i18n->get('save').'">
<input type="hidden" name="step" value="6" />
<input type="hidden" name="logoUrl" value="'.$logoUrl.'" />
<script type="text/javascript">
document.write(WebguiStyleDesigner.draw("^c;","'.$logoUrl.'","'.$storageId.'"));
</script>
<input type="submit" value="'.$i18n->get('save').'">
</form>
';
}
elsif ($session->form->process("step") eq "6") {
my $importNode = WebGUI::Asset->getImportNode($session);
my $form = $session->form;
my $snippet = '/* auto generated by WebGUI '.$WebGUI::VERSION.' */
.clearFloat { clear: both; }
body { background-color: '.$form->get("pageBackgroundColor").'; color: '.$form->get("contentTextColor").'}
a { color: '.$form->get("linkColor").';}
a:visited { color: '.$form->get("visitedLinkColor").'; }
#editToggleContainer { padding: 1px; }
#utilityLinksContainer { float: right; padding: 1px; }
#pageUtilityContainer { font-size: 9pt; background-color: '.$form->get("utilityBackgroundColor").'; color: '.$form->get("utilityTextColor").'; }
#pageHeaderContainer { background-color: '.$form->get("headerBackgroundColor").'; color: '.$form->get("headerTextColor").'; }
#pageHeaderLogoContainer { float: left; padding: 5px; background-color: '.$form->get("headerBackgroundColor").';}
#logo { border: 0px; max-width: 300px; }
#companyNameContainer { float: right; padding: 5px; font-size: 16pt; }
#pageBodyContainer { background-color: '.$form->get("contentBackgroundColor").'; color: '.$form->get("contentTextColor").'; }
#mainNavigationContainer { min-height: 300px; padding: 5px; float: left; width: 180px; font-size: 10pt; background-color: '.$form->get("navigationBackgroundColor").'; }
#mainNavigationContainer A, #mainNavigationContainer A:link { color: '.$form->get("navigationTextColor").'; }
#mainBodyContentContainer { padding: 5px; margin-left: 200px; font-family: serif, times new roman; font-size: 12pt; overflow: auto; }
#pageFooterContainer { text-align: center; background-color: '.$form->get("footerBackgroundColor").'; color: '.$form->get("footerTextColor").'; }
#copyrightContainer { font-size: 8pt; }
#pageWidthContainer { width: 80%; margin-left: auto; margin-right: auto; font-family: sans-serif, helvetica, arial; border: 3px solid black; }
';
my $css = addAsset($importNode, {
title => "my-style.css",
className => "WebGUI::Asset::Snippet",
snippet => $snippet,
isHidden => 1,
mimeType => "text/css",
});
my $styleTemplate = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>^Page(title); - ^c;</title>
<link type="text/css" href="'.$css->getUrl.'" rel="stylesheet" />
<tmpl_var head.tags>
</head>
<body>
^AdminBar;
<div id="pageWidthContainer">
<div id="pageUtilityContainer">
<div id="utilityLinksContainer">^a(^@;); :: ^LoginToggle; :: ^r(Print!);</div>
<div id="editToggleContainer">^AdminToggle;</div>
<div class="clearFloat"></div>
</div>
<div id="pageHeaderContainer">
<div id="companyNameContainer">^c;</div>
<div id="pageHeaderLogoContainer"><a href="^H(linkonly);"><img src="'.$form->get("logoUrl").'" id="logo" alt="logo" /></a></div>
<div class="clearFloat"></div>
</div>
<div id="pageBodyContainer">
<div id="mainNavigationContainer"><p>^AssetProxy("flexmenu");</p></div>
<div id="mainBodyContentContainer">
<tmpl_var body.content>
</div>
<div class="clearFloat"></div>
</div>
<div id="pageFooterContainer">
<div id="copyrightContainer">&copy;^D(%y); ^c;. ^International(All Rights Reserved);.</div>
<div class="clearFloat"></div>
</div>
</div>
</body>
</html>';
my $style = addAsset($importNode, {
className => "WebGUI::Asset::Template",
title => $i18n->get("My Style"),
isHidden => 1,
namespace => "style",
template => $styleTemplate
});
$session->setting->set("userFunctionStyleId",$style->getId);
# collect new page info
my $f = WebGUI::HTMLForm->new($session,action=>$session->url->gateway());
$f->hidden(name=>"step", value=>"7");
$f->hidden(name=>"styleTemplateId", value=>$style->getId);
$f->yesNo(name=>"contactUs",label=>$i18n->get('Contact Us'));
$f->yesNo(name=>"calendar",label=>$i18n->get("assetName", 'Asset_Calendar'));
$f->yesNo(name=>"wiki",label=>$i18n->get('assetName', 'Asset_WikiMaster'));
$f->yesNo(name=>"search",label=>$i18n->get("assetName", 'Asset_Search'));
$f->yesNo(name=>"aboutUs",label=>$i18n->get("About Us"));
$f->HTMLArea(name=>"aboutUsContent", richEditId=>"PBrichedit000000000002",
value=>$i18n->get("Put your about us content here."));
if (exists $session->config->get('assets')->{"WebGUI::Asset::Wobject::Collaboration"}) {
$f->yesNo(name=>"news",label=>$i18n->get(357));
$f->yesNo(name=>"forums",label=>$i18n->get("Forums"));
$f->textarea(name=>"forumNames",subtext=>$i18n->get("One forum name per line"),
value=>$i18n->get("Support")."\n".$i18n->get("General Discussion"));
}
$f->submit;
$legend = $i18n->get("Initial Pages");
$output .= $f->print;
}
elsif ($session->form->process("step") eq "7") {
my $home = WebGUI::Asset->getDefault($session);
my $form = $session->form;
# update default site style
foreach my $asset (@{$home->getLineage(["self","descendants"], {returnObjects=>1})}) {
if (defined $asset) {
$asset->update({styleTemplateId=>$form->get("styleTemplateId")});
}
}
# add new pages
if ($form->get("aboutUs")) {
my $page = addPage($home, $i18n->get("About Us"));
addAsset($page, {
title => $i18n->get("About Us"),
isHidden => 1,
className => "WebGUI::Asset::Wobject::Article",
description => $form->get("aboutUsContent"),
});
}
# add forums
if ($form->get("forums")) {
my $page = addPage($home, $i18n->get("Forums"));
my $board = addAsset($page, {
title => $i18n->get("Forums"),
isHidden => 1,
className => "WebGUI::Asset::Wobject::MessageBoard",
description => $i18n->get("Discuss your ideas and get help from our community."),
});
my $forumNames = $form->get("forumNames");
$forumNames =~ s/\r//g;
foreach my $forumName (split "\n", $forumNames) {
next if $forumName eq "";
addAsset($board, {
title => $forumName,
isHidden => 1,
className => "WebGUI::Asset::Wobject::Collaboration"
});
}
}
# add news
if ($form->get("news")) {
my $page = addPage($home, $i18n->get(357));
addAsset($page, {
title => $i18n->get(357),
isHidden => 1,
className => "WebGUI::Asset::Wobject::Collaboration",
collaborationTemplateId => "PBtmpl0000000000000112",
allowReplies => 0,
attachmentsPerPost => 5,
postFormTemplateId => "PBtmpl0000000000000068",
threadTemplateId => "PBtmpl0000000000000067",
description => $i18n->get("All the news you need to know."),
});
}
# add wiki
if ($form->get("wiki")) {
my $page = addPage($home, $i18n->get("assetName", 'Asset_WikiMaster'));
addAsset($page, {
title => $i18n->get("assetName", 'Asset_WikiMaster'),
isHidden => 1,
allowAttachments => 5,
className => "WebGUI::Asset::Wobject::WikiMaster",
description => $i18n->get("Welcome to our wiki. Here you can help us keep information up to date."),
});
}
# add calendar
if ($form->get("calendar")) {
my $page = addPage($home, $i18n->get('assetName', "Asset_Calendar"));
addAsset($page, {
title => $i18n->get('assetName', "Asset_Calendar"),
isHidden => 1,
className => "WebGUI::Asset::Wobject::Calendar",
description => $i18n->get("Check out what is going on."),
});
}
# add contact us
if ($form->get("contactUs")) {
my $page = addPage($home, $i18n->get("Contact Us"));
my $i18n2 = WebGUI::International->new($session, "Asset_DataForm");
my @fieldConfig = (
{
name=>"from",
label=>$i18n2->get("Your Email Address", 'WebGUI'),
status=>"required",
isMailField=>1,
width=>0,
type=>"email",
},
{
name=>"to",
label=>$i18n2->get(11),
status=>"hidden",
isMailField=>1,
width=>0,
type=>"email",
defaultValue=>$session->setting->get("companyEmail"),
},
{
name=>"cc",
label=>$i18n2->get(12),
status=>"hidden",
isMailField=>1,
width=>0,
type=>"email",
},
{
name=>"bcc",
label=>$i18n2->get(13),
status=>"hidden",
isMailField=>1,
width=>0,
type=>"email",
},
{
name=>"subject",
label=>$i18n2->get(14),
status=>"hidden",
isMailField=>1,
width=>0,
type=>"text",
defaultValue=>$i18n->get(2),
},
{
name => "comments",
label => $i18n->get("comments", 'VersionTag'),
status => "required",
type => "textarea",
subtext => $i18n->get("Tell us how we can assist you."),
},
);
my $dataForm = addAsset($page, {
title => $i18n->get("Contact Us"),
isHidden => 1,
className => "WebGUI::Asset::Wobject::DataForm",
description => $i18n->get("We welcome your feedback."),
acknowledgement => $i18n->get("Thanks for for your interest in ^c;. We will review your message shortly."),
mailData => 1,
fieldConfiguration => JSON::to_json(\@fieldConfig),
});
}
# add search
if ($form->get("search")) {
my $page = addPage($home, $i18n->get('assetName',"Asset_Search"));
addAsset($page, {
title => $i18n->get('assetName',"Asset_Search"),
isHidden => 1,
className => "WebGUI::Asset::Wobject::Search",
description => $i18n->get("Cannot find what you are looking for? Try our search."),
searchRoot => $home->getId,
});
}
# commit the working tag
my $working = WebGUI::VersionTag->getWorking($session);
$working->set({name=>"Initial Site Setup"});
$working->commit;
# remove init state
$session->setting->remove('specialState');
$session->http->setRedirect($session->url->gateway("?setup=complete"));
return undef;
}
else {
$legend = $i18n->get('admin account');
my $u = WebGUI::User->new($session,'3');
my $f = WebGUI::HTMLForm->new($session,action=>$session->url->gateway());
$f->hidden( -name=>"step", -value=>"2");
$f->text(
-name=>"username",
-value=>$u->username,
-label=>$i18n->get(50),
-hoverHelp=>$i18n->get('50 setup description'),
);
$f->text(
-name=>"identifier",
-value=>"123qwe",
-label=>$i18n->get(51),
-hoverHelp=>$i18n->get('51 description'),
-subtext=>'<div style=\"font-size: 10px;\">('.$i18n->get("password clear text").')</div>'
);
$f->email(
-name=>"email",
-value=>$u->profileField("email"),
-label=>$i18n->get(56),
-hoverHelp=>$i18n->get('56 description'),
);
$f->timeZone(
-name => "timeZone",
-value => $u->profileField("timeZone"),
-label => $i18n->get('timezone','DateTime'),
-hoverHelp => $i18n->get('timezone help'),
);
$f->selectBox(
-name => "language",
-value => $u->profileField("language"),
-label => $i18n->get('304'),
-hoverHelp => $i18n->get('language help'),
-options => $i18n->getLanguages(),
);
$f->submit;
$output .= $f->print;
}
my $page = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>'.$i18n->get('WebGUI Initial Configuration').' :: '.$legend.'</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript">
function getWebguiProperty (propName) {
var props = new Array();
props["extrasURL"] = "'.$session->url->extras().'";
props["pageURL"] = "'.$session->url->page(undef, undef, 1).'";
return props[propName];
}
</script>'. $session->style->generateAdditionalHeadTags .'
<style type="text/css">';
if ($session->form->process("step") != 5) {
$page .= ' #initBox {
font-family: georgia, helvetica, arial, sans-serif; color: white; z-index: 10;
top: 5%; left: 10%; position: absolute;
}
#initBoxSleeve {
width: 770px;
height: 475px;
}
a { color: black; }
a:visited { color: black;}
body { margin: 0; }
';
}
else {
$page .= '
#initBox {
font-family: georgia, helvetica, arial, sans-serif; color: white; z-index: 10; width: 98%;
height: 98%; top: 10; left: 10; position: absolute;
}
';
}
$page .= ' </style> </head> <body>
<div id="initBox"><h1>'.$legend.'</h1><div id="initBoxSleeve"> '.$output.'</div></div>
<img src="'.$session->url->extras('background.jpg').'" style="border-style:none;position: absolute; top: 0; left: 0; width: 100%; height: 1000px; z-index: 1;" />
</body> </html>';
$session->http->setMimeType("text/html");
return $page;
}
# Dispatch to the setup wizard
my $wiz = WebGUI::Wizard::Setup->new( $session );
return $wiz->dispatch;
}
1;

View file

@ -88,7 +88,7 @@ sub www_address {
my $session = shift;
my $output = undef;
my $method = "www_". ( $session->form->get("method") || "view");
my $cart = WebGUI::Shop::AddressBook->newBySession($session);
my $cart = WebGUI::Shop::AddressBook->newByUserId($session);
if ($cart->can($method)) {
$output = $cart->$method();

View file

@ -0,0 +1,45 @@
package WebGUI::Content::Wizard;
=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
-------------------------------------------------------------------
=head1 NAME
Package WebGUI::Content::Wizard
=head1 DESCRIPTION
A content handler for WebGUI::Wizard modules. Dispatches to WebGUI::Wizard after process form variables.
=head2 handler ( session )
The content handler for this package.
=cut
sub handler {
my ( $session ) = @_;
if ( $session->form->get('op') eq 'wizard' && $session->form->get('wizard_class') ) {
my $class = $session->form->get('wizard_class');
WebGUI::Pluggable->load($class);
if ( $class->isa( 'WebGUI::Wizard' ) ) {
my $wizard = $class->new( $session );
return $wizard->dispatch;
}
else {
return "Sminternal Smerver Smerror";
}
}
}
1;

View file

@ -91,6 +91,9 @@ our $HELP = {
{ namespace => "Asset_WikiMaster",
tag => "wiki master asset variables"
},
{ namespace => "Asset_WikiMaster",
tag => "keyword page variables"
},
],
variables => [
{ 'name' => 'searchLabel',
@ -102,26 +105,6 @@ our $HELP = {
{ 'name' => 'recentChangesLabel variable', },
{ 'name' => 'addPageUrl', },
{ 'name' => 'addPageLabel', },
{ 'name' => 'keywords_loop',
'variables' => [
{ 'name' => 'title',
'description' => 'keyword title',
},
{ 'name' => 'url',
'description' => 'keyword url',
},
{ 'name' => 'level',
'description' => 'keyword level',
},
{ 'name' => 'indent_loop',
'variables' => [
{ 'name' => 'indent',
'description' => 'keyword indent',
},
],
},
],
},
],
fields => [],
related => [],
@ -278,6 +261,92 @@ our $HELP = {
related => [],
},
'by keyword template' => {
title => 'by keyword template title',
body => '',
isa => [
{ namespace => "Asset_WikiMaster",
tag => "keyword page variables"
},
{ namespace => "WebGUI",
tag => "pagination template variables"
},
],
variables => [
{ 'name' => 'mostPopularUrl', },
{ 'name' => 'recentChangesUrl', },
{ name => 'keyword',
description => 'by keyword keyword',
},
{ name => 'pagesLoop',
description => 'by keyword pagesLoop',
variables => [
{ name => 'title',
description => 'by keyword title',
},
{ name => 'url',
description => 'by keyword url',
},
{ name => 'synopsis',
description => 'by keyword synopsis',
},
],
},
{ name => 'formHeader',
description => 'by keyword formHeader',
},
{ name => 'keywordForm',
description => 'by keyword keywordForm',
},
{ name => 'submitForm',
description => 'by keyword submitForm',
},
{ name => 'formFooter',
description => 'by keyword formFooter',
},
],
fields => [],
related => [],
},
'keyword page variables' => {
title => 'keyword page variables',
body => '',
isa => [ ],
private => 1,
variables => [
{ 'name' => 'keywords_loop',
'variables' => [
{ 'name' => 'title',
'description' => 'keyword title',
},
{ 'name' => 'url',
'description' => 'keyword url',
},
{ 'name' => 'level',
'description' => 'keyword level',
},
{ 'name' => 'descendants',
'description' => 'keyword descendants',
},
{ 'name' => 'isTopLevel',
'description' => 'keyword isTopLevel',
},
{ 'name' => 'indent_loop',
'variables' => [
{ 'name' => 'indent',
'description' => 'keyword indent',
},
],
},
],
},
],
fields => [],
related => [],
},
};
1;

View file

@ -107,17 +107,6 @@ our $HELP = {
name => 'owner',
description => 'help owner',
},
{ 'name' => 'isKeywordPage', },
{ 'name' => 'keyword_page_loop',
'variables' => [
{ 'name' => 'title',
'description' => 'keyword page title',
},
{ 'name' => 'url',
'description' => 'keyword page url',
},
],
},
],
related => [],
},

View file

@ -300,6 +300,50 @@ our $HELP = {
],
},
'cart summary variables' => {
title => 'cart summary variables',
body => 'cart summary variables help',
isa => [],
fields => [],
private => 1,
variables => [
{
name => 'shippableItemsInCart',
namespace => 'Shop',
},
{
name => 'subtotal',
description => 'subtotalPrice help',
namespace => 'Shop',
},
{
name => 'shipping',
description => 'shippingPrice help',
namespace => 'Shop',
},
{
name => 'taxes',
description => 'taxes help',
namespace => 'Shop',
},
{
name => 'inShopCreditAvailable',
description => 'inShopCreditAvailable help',
namespace => 'Shop',
},
{
name => 'inShopCreditDeduction',
description => 'inShopCreditDeduction help',
namespace => 'Shop',
},
{
name => 'totalPrice',
description => 'totalPrice help',
namespace => 'Shop',
},
],
},
};
1;

View file

@ -0,0 +1,30 @@
package WebGUI::Help::PayDriver_Cash;
use strict;
our $HELP = {
'cart summary template' => {
title => 'cart summary template',
body => '',
isa => [
{ namespace => "PayDriver",
tag => "cart summary variables"
},
],
fields => [],
variables => [
{
name => "proceedButton",
required => 1,
namespace => 'PayDriver',
},
],
related => [
],
},
};
1;

View file

@ -0,0 +1,30 @@
package WebGUI::Help::PayDriver_ExpressCheckout;
use strict;
our $HELP = {
'cart summary template' => {
title => 'cart summary template',
body => '',
isa => [
{ namespace => "PayDriver",
tag => "cart summary variables"
},
],
fields => [],
variables => [
{
name => "proceedButton",
required => 1,
namespace => 'PayDriver',
},
],
related => [
],
},
};
1;

View file

@ -8,7 +8,11 @@ our $HELP = {
'edit credentials template' => {
title => 'edit credentials template',
body => 'edit credentials template help',
isa => [],
isa => [
{ namespace => "PayDriver",
tag => "cart summary variables"
},
],
fields => [],
variables => [
{
@ -33,46 +37,6 @@ our $HELP = {
required => 1,
namespace => 'Shop',
},
{
name => "addressField",
description => "addressField help",
required => 1,
},
{
name => "cityField",
description => "cityField help",
required => 1,
namespace => 'Shop',
},
{
name => "stateField",
description => "stateField help",
required => 1,
namespace => 'Shop',
},
{
name => "countryField",
description => "countryField help",
required => 1,
namespace => 'Shop',
},
{
name => "codeField",
description => "codeField help",
required => 1,
namespace => 'Shop',
},
{
name => "phoneField",
description => "phoneNumberField help",
required => 1,
namespace => 'Shop',
},
{
name => "emailField",
description => "emailField help",
required => 1,
},
{
name => "cardNumberField",
description => "cardNumberField help",
@ -92,7 +56,6 @@ our $HELP = {
name => "checkoutButton",
description => "checkoutButton help",
required => 1,
namespace => 'Shop',
},
],
related => [

View file

@ -0,0 +1,30 @@
package WebGUI::Help::PayDriver_Ogone;
use strict;
our $HELP = {
'cart summary template' => {
title => 'cart summary template',
body => '',
isa => [
{ namespace => "PayDriver",
tag => "cart summary variables"
},
],
fields => [],
variables => [
{
name => "proceedButton",
required => 1,
namespace => 'PayDriver',
},
],
related => [
],
},
};
1;

View file

@ -0,0 +1,30 @@
package WebGUI::Help::PayDriver_PayPalStd;
use strict;
our $HELP = {
'cart summary template' => {
title => 'cart summary template',
body => '',
isa => [
{ namespace => "PayDriver",
tag => "cart summary variables"
},
],
fields => [],
variables => [
{
name => "proceedButton",
required => 1,
namespace => 'PayDriver',
},
],
related => [
],
},
};
1;

View file

@ -143,11 +143,6 @@ our $HELP = {
description => "formFooter help",
required => 1,
},
{
name => "checkoutButton",
description => "checkoutButton help",
required => 1,
},
{
name => "updateButton",
description => "updateButton help",
@ -157,15 +152,6 @@ our $HELP = {
name => "continueShoppingButton",
description => "continueShoppingButton help",
},
{
name => "chooseShippingButton",
description => "chooseShippingButton help",
required => 1,
},
{
name => "shipToButton",
description => "shipToButton help",
},
{
name => "subtotalPrice",
description => "subtotalPrice help",

View file

@ -129,6 +129,11 @@ per-user settings for email delivery will not be used. Useful if you want to for
be sent as an Email rather than allowing the user's C<receiveInboxEmailNotifications> setting to
take effect.
=head4 extraHeaders
A hash ref containing extra header information to send to WebGUI::Message::create valid headers include:
cc, bcc, replyTo, returnPath, contentType, messageId, and inReplyTo. See WebGUI::Message::create for more details.
=cut
sub create {
@ -186,13 +191,21 @@ sub create {
}
unless ( $options->{ no_email } ) {
my $subject = (defined $properties->{emailSubject}) ? $properties->{emailSubject} : $self->{_properties}{subject};
my $mail = WebGUI::Mail::Send->create($session, {
toUser=>$self->{_properties}{userId},
toGroup=>$self->{_properties}{groupId},
subject=>$subject,
},
$options->{overridePerUserDelivery} ? undef : 'isInbox',
);
#Set default mail headers
my $mailHeaders = {
toUser=>$self->{_properties}{userId},
toGroup=>$self->{_properties}{groupId},
subject=>$subject,
};
#Add extraHeaders if they are passsed in as options
if($options->{ extraHeaders } && ref $options->{ extraHeaders } eq 'HASH') {
%{$mailHeaders} = (%{$mailHeaders},%{$options->{ extraHeaders }});
}
#Get inbox override flag
my $overridePerUserDelivery = $options->{overridePerUserDelivery} ? undef : 'isInbox';
#Create the mail message
my $mail = WebGUI::Mail::Send->create($session,$mailHeaders,$overridePerUserDelivery);
my $preface = "";
my $fromUser = WebGUI::User->new($session, $properties->{sentBy});
#Don't append prefaces to the visitor users or messages that don't specify a user (default case)

View file

@ -42,6 +42,10 @@ sub process {
if (! defined $time) {
$time = time();
}
else {
$time =~ s/^\s+//;
$time =~ s/\s+$//;
}
my $temp = $session->datetime->epochToHuman($time, $_[0]);
return $temp;
}

View file

@ -0,0 +1,82 @@
package WebGUI::Role::Asset::AutoSynopsis;
=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 Moose::Role;
use WebGUI::HTML;
=head1 NAME
Package WebGUI::AssetAspect::AutoSynopsis
=head1 DESCRIPTION
This is a role which provides a method for an asset to create a synopsis based on user submitted content.
=head1 SYNOPSIS
with 'WebGUI::Role::Asset::AutoSynopsis';
=head1 METHODS
These methods are available from this class:
=cut
#-------------------------------------------------------------------
=head2 getSynopsisAndContent ($synopsis, $body)
Returns a synopsis taken from the body of the Post, based on either the separator
macro, the first html paragraph, or the first physical line of text as defined by
newlines.
Returns both the synopsis, and the original body content.
=head3 $synopsis
If passed in, it returns that instead of the calculated synopsis.
=head3 $body
Body of the Post to use a source for the synopsis.
=cut
sub getSynopsisAndContent {
my $self = shift;
my $synopsis = shift;
my $body = shift;
unless ($synopsis) {
my @content;
if( $body =~ /\^\-\;/ ) {
my @pieces = WebGUI::HTML::splitSeparator($body);
$content[0] = shift @pieces;
$content[1] = join '', @pieces;
}
elsif( $body =~ /<p>/ ) {
@content = WebGUI::HTML::splitTag($body);
}
else {
@content = split("\n",$body);
}
shift @content if $content[0] =~ /^\s*$/;
$synopsis = WebGUI::HTML::filter($content[0],"all");
}
return ($synopsis,$body);
}
1;

View file

@ -14,6 +14,7 @@ package WebGUI::Role::Asset::Subscribable;
=cut
use strict;
use Moose::Role;
use WebGUI::Definition::Asset;
@ -39,6 +40,7 @@ sub _subscriptionTemplateId_namespace {
return $self->getSubscriptionTemplateNamespace($self->session);
}
use WebGUI::International;
use WebGUI::Mail::Send;
=head1 NAME

View file

@ -9,6 +9,7 @@ use WebGUI::Exception::Shop;
use WebGUI::Form;
use WebGUI::International;
use WebGUI::Shop::Address;
use Scalar::Util qw/blessed/;
=head1 NAME
@ -56,22 +57,87 @@ sub addAddress {
#-------------------------------------------------------------------
=head2 create ( session )
=head2 appendAddressFormVars ( $var, $properties, $prefix )
Constructor. Creates a new address book for this user or session if no user is logged in.
Add template variables for building a form to edit an address to an existing set of template variables.
=head3 $var
A hash ref of template variables.
=head3 $properties
A hash ref of properties to assign to as default to the form variables.
=head3 $prefix
An optional prefix to add to each variable name, and form name.
=cut
sub appendAddressFormVars {
my ($self, $var, $prefix, $properties ) = @_;
my $session = $self->session;
my $form = $session->form;
$properties ||= {};
$prefix ||= '';
$var ||= {};
for ( qw{ address1 address2 address3 label firstName lastName city state organization } ) {
$var->{ $prefix . $_ . 'Field' } = WebGUI::Form::text( $session, {
name => $prefix . $_,
maxlength => 35,
defaultValue => $properties->{ $_ } || $form->get($prefix . $_),
} );
}
$var->{ $prefix . 'countryField' } =
WebGUI::Form::country( $session,{
name => $prefix . 'country',
defaultValue => $properties->{ country } || $form->get($prefix . 'country' ),
} );
$var->{ $prefix . 'codeField' } =
WebGUI::Form::zipcode( $session, {
name => $prefix . 'code',
defaultValue => $properties->{ code } || $form->get($prefix . 'code' ),
} );
$var->{ $prefix . 'phoneNumberField' } =
WebGUI::Form::phone( $session, {
name => $prefix . 'phoneNumber',
defaultValue => $properties->{ phoneNumber } || $form->get($prefix . 'phoneNumber' ),
} );
$var->{ $prefix . 'emailField' } =
WebGUI::Form::email( $session, {
name => $prefix . 'email',
defaultValue => $properties->{ email } || $form->get($prefix . 'email' ),
} );
}
#-------------------------------------------------------------------
=head2 create ( session, userId )
Constructor. Creates a new address book for this user.
=head3 session
A reference to the current session.
=head3 userId
The userId for the user. Throws an exception if it is Visitor. Defaults to the session
user if omitted.
=cut
sub create {
my ($class, $session) = @_;
my ($class, $session, $userId) = @_;
unless (defined $session && $session->isa("WebGUI::Session")) {
WebGUI::Error::InvalidObject->throw(expected=>"WebGUI::Session", got=>(ref $session), error=>"Need a session.");
}
my $id = $session->db->setRow("addressBook", "addressBookId", {addressBookId=>"new", userId=>$session->user->userId, sessionId=>$session->getId});
$userId ||= $session->user->userId;
if ($userId eq '1') {
WebGUI::Error::InvalidParam->throw(error=>"Visitor cannot have an address book.");
}
my $id = $session->db->setRow("addressBook", "addressBookId", {addressBookId=>"new", userId=>$userId});
return $class->new($session, $id);
}
@ -157,6 +223,30 @@ sub getAddress {
#-------------------------------------------------------------------
=head2 getAddressByLabel ( label )
Returns an address object.
=head3 id
An address object's label, e.g. 'Home', 'Work'
=cut
sub getAddressByLabel {
my ($self, $label) = @_;
my $sql = q{
SELECT addressId
FROM address
WHERE addressBookId = ?
AND label = ?
};
my $id = $self->session->db->quickScalar($sql, [$self->getId, $label]);
return $id && $self->getAddress($id);
}
#-------------------------------------------------------------------
=head2 getAddresses ( )
Returns an array reference of address objects that are in this book.
@ -216,6 +306,36 @@ sub getId {
#-------------------------------------------------------------------
=head2 missingFields ( $address )
Returns a list of missing, required fields in this address.
=head3 $address
An address. If it's an WebGUI::Shop::Address object, it will use the data
from it. Otherwise, it will assume that $address is just a hashref.
=cut
sub missingFields {
my $self = shift;
my $address = shift;
my $addressData;
if (blessed $address && $address->isa('WebGUI::Shop::Address')) {
$addressData = $address->get();
}
else {
$addressData = $address;
}
my @missingFields = ();
FIELD: foreach my $field (qw/label firstName lastName address1 city code country phoneNumber/) {
push @missingFields, $field if $addressData->{$field} eq '';
}
return @missingFields;
}
#-------------------------------------------------------------------
=head2 new ( session, addressBookId )
Constructor. Instanciates an addressBook based upon a addressBookId.
@ -251,33 +371,36 @@ sub new {
#-------------------------------------------------------------------
=head2 newBySession ( session )
=head2 newByUserId ( session, userId )
Constructor. Creates a new address book for this user if they don't have one. If the user is not logged in creates an address book attached to the session if there isn't one for the session. In any case returns a reference to the address book.
Constructor. Creates a new address book for this user if they don't have one. In any case returns a reference to the address book.
=head3 session
A reference to the current session.
=head3 userId
The userId for the user. Throws an exception if it is Visitor. Defaults to the session
user if omitted.
=cut
sub newBySession {
my ($class, $session) = @_;
sub newByUserId {
my ($class, $session, $userId) = @_;
unless (defined $session && $session->isa("WebGUI::Session")) {
WebGUI::Error::InvalidObject->throw(expected=>"WebGUI::Session", got=>(ref $session), error=>"Need a session.");
}
my $userId = $session->user->userId;
$userId ||= $session->user->userId;
if ($userId eq '1') {
WebGUI::Error::InvalidParam->throw(error=>"Visitor cannot have an address book.");
}
# check to see if this user or his session already has an address book
my @ids = $session->db->buildArray("select addressBookId from addressBook where (userId<>'1' and userId=?) or sessionId=?",[$session->user->userId, $session->getId]);
my @ids = $session->db->buildArray("select addressBookId from addressBook where userId=?",[$userId]);
if (scalar(@ids) > 0) {
my $book = $class->new($session, $ids[0]);
# convert it to a specific user if we can
if ($userId ne '1') {
$book->update({userId => $userId, sessionId => ''});
}
# merge others if needed
if (scalar(@ids) > 1) {
# it's attached to the session or we have too many so lets merge them
@ -299,6 +422,46 @@ sub newBySession {
}
#-------------------------------------------------------------------
=head2 processAddressForm ( $prefix )
Process the current set of form variables for any belonging to the address book. Returns
a hash ref of address information.
=head3 $prefix
An optional prefix to be added to each form variable.
=cut
sub processAddressForm {
my ($self, $prefix) = @_;
$prefix ||= '';
my $form = $self->session->form;
my %addressData = (
label => $form->get($prefix . "label"),
firstName => $form->get($prefix . "firstName"),
lastName => $form->get($prefix . "lastName"),
address1 => $form->get($prefix . "address1"),
address2 => $form->get($prefix . "address2"),
address3 => $form->get($prefix . "address3"),
city => $form->get($prefix . "city"),
state => $form->get($prefix . "state"),
code => $form->get($prefix . "code", "zipcode"),
country => $form->get($prefix . "country", "country"),
phoneNumber => $form->get($prefix . "phoneNumber", "phone"),
email => $form->get($prefix . "email", "email"),
organization => $form->get($prefix . "organization"),
);
#my $label = $field eq 'address1' ? 'address'
# : $field eq 'phoneNumber' ? 'phone number'
# : $field
# ;
return %addressData;
}
#-------------------------------------------------------------------
=head2 update ( properties )
@ -313,10 +476,6 @@ A hash reference that contains one of the following:
Assign the user that owns this address book.
=head4 sessionId
Assign the session, by id, that owns this address book. Will automatically be set to "" if a user owns it.
=head4 defaultAddressId
The id of the address to be made the default for this address book.
@ -326,18 +485,56 @@ The id of the address to be made the default for this address book.
sub update {
my ($self, $newProperties) = @_;
my $id = id $self;
foreach my $field (qw(userId sessionId defaultAddressId)) {
foreach my $field (qw(userId defaultAddressId)) {
$properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field};
}
##Having both a userId and sessionId will confuse create.
if ($properties{$id}{userId} ne "") {
$properties{$id}{sessionId} = "";
}
$self->session->db->setRow("addressBook","addressBookId",$properties{$id});
}
#-------------------------------------------------------------------
=head2 www_ajaxGetAddress ( )
Gets a JSON object representing the address given by the addressId form
parameter
=cut
sub www_ajaxGetAddress {
my $self = shift;
my $session = $self->session;
$session->http->setMimeType('text/plain');
my $addressId = $session->form->get('addressId');
my $address = $self->getAddress($addressId) or return;
return JSON->new->encode($address->get);
}
#-------------------------------------------------------------------
=head2 www_ajaxSave ( )
Saves an address book entry
=cut
sub www_ajaxSave {
my $self = shift;
my $session = $self->session;
my $address = JSON->new->decode($session->form->get('address'));
my $obj = $self->getAddressByLabel($address->{label});
if ($obj) {
$obj->update($address);
}
else {
$obj = $self->addAddress($address);
}
$session->http->setMimeType('text/plain');
return $obj->getId;
}
#-------------------------------------------------------------------
=head2 www_deleteAddress ( )
Deletes an address from the book.
@ -483,46 +680,11 @@ Saves the address. If there is a problem generates www_editAddress() with an err
sub www_editAddressSave {
my $self = shift;
my $form = $self->session->form;
my $i18n = WebGUI::International->new($self->session,"Shop");
if ($form->get("label") eq "") {
return $self->www_editAddress(sprintf($i18n->get('is a required field'), $i18n->get('label')));
}
if ($form->get("firstName") eq "") {
return $self->www_editAddress(sprintf($i18n->get('is a required field'), $i18n->get('firstName')));
}
if ($form->get("lastName") eq "") {
return $self->www_editAddress(sprintf($i18n->get('is a required field'), $i18n->get('lastName')));
}
if ($form->get("address1") eq "") {
return $self->www_editAddress(sprintf($i18n->get('is a required field'), $i18n->get('address')));
}
if ($form->get("city") eq "") {
return $self->www_editAddress(sprintf($i18n->get('is a required field'), $i18n->get('city')));
}
if ($form->get("code") eq "") {
return $self->www_editAddress(sprintf($i18n->get('is a required field'), $i18n->get('code')));
}
if ($form->get("country") eq "") {
return $self->www_editAddress(sprintf($i18n->get('is a required field'), $i18n->get('country')));
}
if ($form->get("phoneNumber") eq "") {
return $self->www_editAddress(sprintf($i18n->get('is a required field'), $i18n->get('phone number')));
}
my %addressData = (
label => $form->get("label"),
firstName => $form->get("firstName"),
lastName => $form->get("lastName"),
address1 => $form->get("address1"),
address2 => $form->get("address2"),
address3 => $form->get("address3"),
city => $form->get("city"),
state => $form->get("state"),
code => $form->get("code","zipcode"),
country => $form->get("country","country"),
phoneNumber => $form->get("phoneNumber","phone"),
email => $form->get("email","email"),
organization => $form->get("organization"),
);
my %addressData = $self->processAddressForm();
my @missingFields = $self->missingFields(\%addressData);
if (@missingFields) {
return $self->www_editAddress(pop @missingFields);
}
if ($form->get('addressId') eq '') {
$self->addAddress(\%addressData);
}

View file

@ -12,9 +12,11 @@ use WebGUI::Shop::AddressBook;
use WebGUI::Shop::CartItem;
use WebGUI::Shop::Credit;
use WebGUI::Shop::Ship;
use WebGUI::Shop::Pay;
use WebGUI::Shop::Tax;
use WebGUI::User;
use Tie::IxHash;
use Data::Dumper;
=head1 NAME
@ -38,7 +40,7 @@ These subroutines are available from this package:
readonly session => my %session;
private properties => my %properties;
private error => my %error;
public error => my %error;
private addressBookCache => my %addressBookCache;
#-------------------------------------------------------------------
@ -76,15 +78,11 @@ The amount to calculate the deduction against. Defaults to calculateTotal().
sub calculateShopCreditDeduction {
my ($self, $total) = @_;
# cannot use in-shop credit on recurring items
foreach my $item (@{$self->getItems}) {
if ($item->getSku->isRecurring) {
return $self->formatCurrency(0);
}
}
unless (defined $total) {
$total = $self->calculateTotal
}
# cannot use in-shop credit on recurring items
return $self->formatCurrency(0) if $self->requiresRecurringPayment;
return $self->formatCurrency(WebGUI::Shop::Credit->new($self->session, $self->get('posUserId'))->calculateDeduction($total));
}
@ -263,13 +261,45 @@ sub getAddressBook {
my $self = shift;
my $id = id $self;
unless (exists $addressBookCache{$id}) {
$addressBookCache{$id} = WebGUI::Shop::AddressBook->newBySession($self->session);
$addressBookCache{$id} = WebGUI::Shop::AddressBook->newByUserId($self->session);
}
return $addressBookCache{$id};
}
#-------------------------------------------------------------------
=head2 getBillingAddress ()
Returns the WebGUI::Shop::Address object that is attached to this cart for billing.
=cut
sub getBillingAddress {
my $self = shift;
my $book = $self->getAddressBook;
if (my $addressId = $self->get("billingAddressId")) {
return $book->getAddress($addressId);
}
my $address = $book->getDefaultAddress;
$self->update({billingAddressId=>$address->getId});
return $address;
}
#-------------------------------------------------------------------
=head2 getPaymentGateway ()
Returns the WebGUI::Shop::PayDriver object that is attached to this cart for payment.
=cut
sub getPaymentGateway {
my $self = shift;
return WebGUI::Shop::Pay->new($self->session)->getPaymentGateway($self->get("gatewayId"));
}
#-------------------------------------------------------------------
=head2 getId ()
Returns the unique id for this cart.
@ -285,7 +315,9 @@ sub getId {
=head2 getItem ( itemId )
Returns a reference to a WebGUI::Shop::CartItem object.
Returns a reference to a WebGUI::Shop::CartItem object. Throws an WebGUI::Error::InvalidParam
exception if no itemId is passed, or if an invalid itemId is passed. It will not catch any
exceptions thrown by actually creating the CartItem, the caller of this method should do that.
=head3 itemId
@ -295,7 +327,7 @@ The id of the item to retrieve.
sub getItem {
my ($self, $itemId) = @_;
unless (defined $itemId && $itemId =~ m/^[A-Za-z0-9_-]{22}$/) {
unless (defined $itemId && $self->session->id->valid($itemId)) {
WebGUI::Error::InvalidParam->throw(error=>"Need an itemId.");
}
my $item = WebGUI::Shop::CartItem->new($self, $itemId);
@ -499,30 +531,76 @@ Returns whether all the required properties of the the cart are set.
sub readyForCheckout {
my $self = shift;
my $session = $self->session;
my $book = $self->getAddressBook;
# Check if the billing address is set and correct
my $address = eval{$self->getBillingAddress};
if (WebGUI::Error->caught) {
$self->error('no billing address');
return 0;
}
if (my @missingFields = $book->missingFields($address->get)) {
$self->error($missingFields[0]);
return 0;
}
# Check if the shipping address is set and correct
my $address = eval{$self->getShippingAddress};
return 0 if WebGUI::Error->caught;
my $shipAddress = eval{$self->getShippingAddress};
if (WebGUI::Error->caught) {
$self->error('no shipping address');
return 0;
}
if (my @missingFields = $book->missingFields($shipAddress->get)) {
$self->error($missingFields[0]);
return 0;
}
if ($self->requiresShipping) {
##Must have a configured shipping id.
if (! $self->get('shipperId')) {
$self->error('no shipping method set');
return 0;
}
my $shipper = eval { WebGUI::Shop::ShipDriver->new($session, $self->get('shipperId'))};
if (my $e = WebGUI::Error->caught) {
$self->error($e->error);
return 0;
}
}
# Check if the cart has items
return 0 unless scalar @{ $self->getItems };
# fail if there are multiple recurring items or if
# fail if there are multiple recurring items
return 0 if ($self->hasMixedItems);
# Check minimum cart checkout requirement
my $total = eval { $self->calculateTotal };
if (my $e = WebGUI::Error->caught) {
$error{id $self} = $e->error;
$self->error($e->error);
return 0;
}
my $requiredAmount = $self->session->setting->get( 'shopCartCheckoutMinimum' );
if ( $requiredAmount > 0 ) {
return 0 if $total < $requiredAmount;
if ( $requiredAmount > 0 && $total < $requiredAmount) {
$self->error('required amount not met in cart');
return 0;
}
##Must have a configured shipping id.
return 0 if ! $self->get('shipperId');
##Must have a configured payment method.
if (! $self->get('gatewayId')) {
$self->error('no payment gateway set');
return 0;
}
my $gateway = eval { WebGUI::Shop::PayDriver->new($session, $self->get('gatewayId'))};
if (my $e = WebGUI::Error->caught) {
$self->error($e->error);
return 0;
}
##Check for any other logged errors
return 0 if $error{ id $self };
@ -553,6 +631,26 @@ sub requiresRecurringPayment {
#-------------------------------------------------------------------
=head2 requiresShipping ( )
Returns whether any item in this cart requires shipping.
=cut
sub requiresShipping {
my $self = shift;
# Look for recurring items in the cart
foreach my $item (@{ $self->getItems }) {
return 1 if $item->getSku->isShippingRequired;
}
# No recurring items in cart so return false
return 0;
}
#-------------------------------------------------------------------
=head2 update ( properties )
Sets properties in the cart.
@ -565,6 +663,10 @@ A hash reference that contains one of the following:
The unique id for a shipping address attached to this cart.
=head4 billingAddressId
The unique id for a billing address attached to this cart.
=head4 shipperId
The unique id of the configured shipping driver that will be used to ship these goods.
@ -585,7 +687,7 @@ sub update {
WebGUI::Error::InvalidParam->throw(error=>"Need a properties hash ref.");
}
my $id = id $self;
foreach my $field (qw(shippingAddressId posUserId shipperId creationDate)) {
foreach my $field (qw(billingAddressId shippingAddressId posUserId gatewayId shipperId creationDate)) {
$properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field};
}
$self->session->db->setRow("cart","cartId",$properties{$id});
@ -595,7 +697,7 @@ sub update {
=head2 updateFromForm ( )
Updates the cart totals.
Updates the cart totals, the address fields and the shipping and billing options from form data.
=cut
@ -613,49 +715,154 @@ sub updateFromForm {
$error{id $self} = "An unknown error has occured: ".$e->message;
}
}
if (my $itemAddressId = $form->get("itemAddress_".$item->getId)) {
$item->update({shippingAddressId => $itemAddressId});
}
}
if ($self->hasMixedItems) {
my $i18n = WebGUI::International->new($self->session, "Shop");
$error{id $self} = $i18n->get('mixed items warning');
}
my $book = $self->getAddressBook;
my $cartProperties = {};
$cartProperties->{ shipperId } = $form->process( 'shipperId' ) if $form->process( 'shipperId' );
my %billingData = $book->processAddressForm('billing_');
my @missingBillingFields = $book->missingFields(\%billingData);
my $billingAddressId = $form->process('billingAddressId');
if ($billingAddressId eq 'new_address' && ! @missingBillingFields) {
##Add a new address
my $newAddress = $book->addAddress(\%billingData);
$cartProperties->{billingAddressId} = $newAddress->get('addressId');
}
elsif ($billingAddressId eq 'update_address' && $self->get('billingAddressId') && ! @missingBillingFields) {
##User updated the current address
my $address = $self->getBillingAddress();
$address->update(\%billingData);
}
elsif ($billingAddressId ne 'new_address' && $billingAddressId) {
##User changed the address selector to another address field
$cartProperties->{billingAddressId} = $billingAddressId;
}
elsif (@missingBillingFields) {
$self->error('missing billing '.$missingBillingFields[0]);
}
else {
$self->session->log->warn('billing address: something else: ');
}
##Update now, so that you can add an address AND set the shipping address to be the same at the same time.
$self->update($cartProperties);
if ($self->requiresShipping) {
if ($form->process('sameShippingAsBilling', 'yesNo')) {
$cartProperties->{shippingAddressId} = $self->get('billingAddressId');
}
else {
my %shippingData = $book->processAddressForm('shipping_');
my @missingShippingFields = $book->missingFields(\%shippingData);
my $shippingAddressId = $form->process('shippingAddressId');
##No missing shipping fields, if we set to the same as the billing fields
if (@missingShippingFields) {
$self->error('missing shipping '.$missingShippingFields[0]);
}
if ($shippingAddressId eq 'new_address' && ! @missingShippingFields) {
##Add a new address
my $newAddress = $book->addAddress(\%shippingData);
$cartProperties->{shippingAddressId} = $newAddress->get('addressId');
}
elsif ($shippingAddressId eq 'update_address' && $self->get('shippingAddressId') && ! @missingShippingFields) {
##User changed the address selector
my $address = $self->getBillingAddress();
$address->update(\%shippingData);
}
elsif ($shippingAddressId ne 'new_address' && $shippingAddressId) {
$cartProperties->{shippingAddressId} = $shippingAddressId;
}
else {
$self->session->log->warn('shipping address: something else: ');
}
}
}
$cartProperties->{ shipperId } = $form->process( 'shipperId' ) if $form->process( 'shipperId' );
$cartProperties->{ gatewayId } = $form->process( 'gatewayId' ) if $form->process( 'gatewayId' );
$self->update( $cartProperties );
my @cartItemIds = $form->process('remove_item', 'checkList');
foreach my $cartItemId (@cartItemIds) {
my $item = eval { $self->getItem($cartItemId); };
$item->remove if ! Exception::Class->caught();
}
}
#-------------------------------------------------------------------
=head2 www_checkout ( )
=head2 www_ajaxPrices
Update the cart and then redirect the user to the payment gateway screen.
Input: shippingId (an addressId)
billingId (an addressId)
Output: {
tax : 1.25,
subtotal : 12.00,
shipping : {
slfjaldjfalfja: {
label : 'USPS',
price : 12.50,
hasPrice : 1 || 0
},
{ ... },
{ ... }
}
}
Takes an addressId and returns JSON shipping options for it, in the form .
=cut
sub www_checkout {
my $self = shift;
$self->updateFromForm;
if ($error{id $self} ne "") {
return $self->www_view;
}
$self->session->http->setRedirect($self->session->url->page('shop=pay;method=selectPaymentGateway'));
return undef;
sub www_ajaxPrices {
my $self = shift;
my $session = $self->session;
my $form = $session->form;
my $billing = $form->get('billingId');
my $shipping = $form->get('shippingId');
my $response = {
subtotal => $self->calculateSubtotal(),
tax => eval {
my $addr = $shipping || $billing or die;
$self->update({ shippingAddressId => $addr });
$self->calculateTaxes();
} || 0,
shipping => eval {
die unless $shipping;
$self->update({ shippingAddressId => $shipping });
my $ship = WebGUI::Shop::Ship->new($self->session);
$ship->getOptions($self);
} || [],
};
$session->http->setMimeType('text/plain');
return JSON->new->encode($response);
}
#-------------------------------------------------------------------
=head2 www_continueShopping ( )
=head2 www_ajaxSetCartItemShippingId
Update the cart and the return the user back to the asset.
Sets the shippingAddressId for a particular cartItem
=cut
sub www_continueShopping {
my $self = shift;
$self->updateFromForm;
if ($error{id $self} ne "") {
return $self->www_view;
}
return undef;
sub www_ajaxSetCartItemShippingId {
my $self = shift;
my $session = $self->session;
my $form = $session->form;
my $item = $self->getItem($form->get('itemId'));
my $address = $form->get('addressId') || undef;
$item && $item->update({ shippingAddressId => $address });
$session->http->setMimeType('text/plain');
return 'ok';
}
#-------------------------------------------------------------------
@ -683,53 +890,47 @@ sub www_lookupPosUser {
return $self->www_view;
}
#-------------------------------------------------------------------
=head2 www_removeItem ( )
Remove an item from the cart and then display the cart again.
=cut
sub www_removeItem {
my $self = shift;
my $item = $self->getItem($self->session->form->get("itemId"));
$item->remove;
return $self->www_view;
}
#-------------------------------------------------------------------
=head2 www_setShippingAddress ()
Sets the shipping address for the cart or for a cart item if itemId is one of the form params.
=cut
sub www_setShippingAddress {
my $self = shift;
my $form = $self->session->form;
if ($form->get("itemId") ne "") {
$self->getItem($form->get("itemId"))->update({shippingAddressId=>$form->get('addressId')});
}
else {
$self->update({shippingAddressId=>$form->get('addressId')});
}
return $self->www_view;
}
#-------------------------------------------------------------------
=head2 www_update ( )
Updates the cart totals and then displays the cart again.
Updates the cart totals, addresses, shipping driver and payment gateway. If requested, and the
cart is ready, calls the www_getCredentials method from the selected payment gateway.
If the cart total, after taxes, shipping, coupons and shop credit is zero, does the checkout
immediately without calling a payment gateway.
Otherwise, returns the user back to the cart.
=cut
sub www_update {
my $self = shift;
my $self = shift;
my $session = $self->session;
$self->updateFromForm;
if ($session->form->get('continue_shopping')) {
return undef;
}
elsif ($session->form->get('checkout')) {
##Setting a shipping address greatly simplifies the Transaction
if (! $self->requiresShipping && ! $self->get('shippingAddressId')) {
$self->update({shippingAddressId => $self->get('billingAddressId')});
}
if ($self->readyForCheckout()) {
my $total = $self->calculateTotal;
##Handle rounding errors, and checkout immediately if the amount is 0 since
##at least the ITransact driver won't accept $0 checkout.
if (sprintf('%.2f', $total + $self->calculateShopCreditDeduction($total)) eq '0.00') {
my $transaction = WebGUI::Shop::Transaction->create($session, {self => $self});
$transaction->completePurchase('zero', 'success', 'success');
$self->onCompletePurchase;
$transaction->sendNotifications();
return $transaction->thankYou();
}
my $gateway = $self->getPaymentGateway;
return $gateway->www_getCredentials;
}
}
return $self->www_view;
}
@ -742,28 +943,16 @@ Displays the shopping cart.
=cut
sub www_view {
my $self = shift;
my $self = shift;
my $session = $self->session;
my $url = $session->url;
my $i18n = WebGUI::International->new($session, "Shop");
my @items = ();
my $url = $session->url;
my $form = $session->form;
my $i18n = WebGUI::International->new($session, "Shop");
my $taxDriver = WebGUI::Shop::Tax->getDriver( $session );
if($url->forceSecureConnection()){
return "redirect";
}
# set up html header
$session->style->setRawHeadTags(q|
<script type="text/javascript">
function setCallbackForAddressChooser (form, itemId) {
form.shop.value='address';
form.method.value='view';
itemId = (itemId == undefined) ? 'null' : "'" + itemId + "'";
form.callback.value='{"url":"|.$url->page.q|","params":[{"name":"shop","value":"cart"},{"name":"method","value":"setShippingAddress"},{"name":"itemId","value":'+itemId+'}]}';
form.submit();
}
</script>
|);
my @cartItems = @{$self->getItems};
if(scalar(@cartItems) < 1) {
@ -776,133 +965,242 @@ sub www_view {
my $template = WebGUI::Asset::Template->newById($session, $session->setting->get("shopCartTemplateId"));
return $session->style->userStyle($template->process(\%var));
}
my %var = (
%{$self->get},
formHeader => WebGUI::Form::formHeader($session)
. WebGUI::Form::hidden($session, {name=>"shop", value=>"cart"})
. WebGUI::Form::hidden($session, {name=>"method", value=>"update"})
. WebGUI::Form::hidden($session, {name=>"itemId", value=>""})
,
formFooter => WebGUI::Form::formFooter($session),
updateButton => WebGUI::Form::submit($session, {value=>$i18n->get("update cart button"), id=>"updateCartButton"}),
checkoutButton => WebGUI::Form::submit($session, {name => 'checkout', value=>$i18n->get("checkout button"), id=>"checkoutButton"}),
continueShoppingButton => WebGUI::Form::submit($session, {
name => 'continue_shopping',
value => $i18n->get("continue shopping button"),
id => 'continueShoppingButton',
}),
minimumCartAmount => $session->setting->get( 'shopCartCheckoutMinimum' ) > 0
? sprintf( '%.2f', $session->setting->get( 'shopCartCheckoutMinimum' ) )
: 0
,
userIsVisitor => $session->user->isVisitor,
shippableItemsInCart => $self->requiresShipping,
);
# get the shipping address
my $address = eval { $self->getShippingAddress };
if (my $e = WebGUI::Error->caught("WebGUI::Error::ObjectNotFound") && $self->get('shippingAddressId')) {
# choose another address cuz we've got a problem
$self->update({shippingAddressId=>''});
}
# generate template variables for the items in the cart
my @items = ();
tie my %addressOptions, 'Tie::IxHash';
if (! $var{userIsVisitor}) {
my $addressBook = $self->getAddressBook;
my $addresses = $addressBook->getAddresses;
foreach my $address (@{ $addresses }) {
$addressOptions{$address->get('addressId')} = $address->get('label');
}
}
tie my %specialAddressOptions, 'Tie::IxHash';
$specialAddressOptions{''} = $i18n->get("Special shipping");
%specialAddressOptions = (%specialAddressOptions, %addressOptions);
foreach my $item (@cartItems) {
my $sku = $item->getSku;
$sku->applyOptions($item->get("options"));
my %properties = (
%{$item->get},
url => $sku->getUrl("shop=cart;method=viewItem;itemId=".$item->getId),
quantityField => WebGUI::Form::integer($session, {name=>"quantity-".$item->getId, value=>$item->get("quantity")}),
isUnique => ($sku->getMaxAllowedInCart == 1),
isShippable => $sku->isShippingRequired,
extendedPrice => $self->formatCurrency($sku->getPrice * $item->get("quantity")),
price => $self->formatCurrency($sku->getPrice),
removeButton => WebGUI::Form::submit($session, {value=>$i18n->get("remove button"),
extras=>q|onclick="this.form.method.value='removeItem';this.form.itemId.value='|.$item->getId.q|';this.form.submit;"|}),
shipToButton => WebGUI::Form::submit($session, {value=>$i18n->get("ship to button"),
extras=>q|onclick="setCallbackForAddressChooser(this.form,'|.$item->getId.q|');"|}),
);
my $address = eval {$item->getShippingAddress};
unless (WebGUI::Error->caught) {
$properties{shippingAddress} = $address->getHtmlFormatted;
url => $sku->getUrl("shop=cart;method=viewItem;itemId=".$item->getId),
quantityField => WebGUI::Form::integer($session, {name=>"quantity-".$item->getId, value=>$item->get("quantity"), size=>5,}),
isUnique => ($sku->getMaxAllowedInCart == 1),
isShippable => $sku->isShippingRequired,
extendedPrice => $self->formatCurrency($sku->getPrice * $item->get("quantity")),
price => $self->formatCurrency($sku->getPrice),
removeBox => WebGUI::Form::checkbox($session, {name => 'remove_item', value => $item->get('itemId')}),
);
my $itemAddress = eval {$item->getShippingAddress};
my $itemAddressId;
if ((!WebGUI::Error->caught) && $itemAddress && $address && $itemAddress->getId ne $address->getId) {
$properties{shippingAddress} = $itemAddress->getHtmlFormatted;
$itemAddressId = $itemAddress->getId;
}
else {
$properties{shippingAddress} = '';
$itemAddressId = '';
}
if (! $var{userIsVisitor} && @cartItems > 1) {
$properties{itemAddressChooser} = WebGUI::Form::selectBox($session, {
name => "itemAddress_".$item->getId,
value => $itemAddressId,
options => \%specialAddressOptions,
extras => q|class="itemAddressMenu"|,
});
}
$taxDriver->appendCartItemVars( \%properties, $item );
push(@items, \%properties);
}
my %var = (
%{$self->get},
items => \@items,
formHeader => WebGUI::Form::formHeader($session)
. WebGUI::Form::hidden($session, {name=>"shop", value=>"cart"})
. WebGUI::Form::hidden($session, {name=>"method", value=>"update"})
. WebGUI::Form::hidden($session, {name=>"itemId", value=>""})
. WebGUI::Form::hidden($session, {name=>"callback", value=>""}),
formFooter => WebGUI::Form::formFooter($session),
updateButton => WebGUI::Form::submit($session, {value=>$i18n->get("update cart button"), extras=>q|id="updateCartButton"|}),
checkoutButton => WebGUI::Form::submit($session, {value=>$i18n->get("checkout button"),
extras=>q|onclick="this.form.method.value='checkout';this.form.submit;" id="checkoutButton"|}),
continueShoppingButton => WebGUI::Form::submit($session, {value=>$i18n->get("continue shopping button"),
extras=>q|onclick="this.form.method.value='continueShopping';this.form.submit;" id="continueShoppingButton"|}),
chooseShippingButton => WebGUI::Form::submit($session, {value=>$i18n->get("choose shipping button"),
extras=>q|onclick="setCallbackForAddressChooser(this.form);" id="chooseAddressButton"|}),
shipToButton => WebGUI::Form::submit($session, {value=>$i18n->get("ship to button"),
extras=>q|onclick="setCallbackForAddressChooser(this.form);"|}),
subtotalPrice => $self->formatCurrency($self->calculateSubtotal()),
minimumCartAmount => $session->setting->get( 'shopCartCheckoutMinimum' ) > 0
? sprintf( '%.2f', $session->setting->get( 'shopCartCheckoutMinimum' ) )
: 0
,
);
# get the shipping address
my $address = eval { $self->getShippingAddress };
if (my $e = WebGUI::Error->caught("WebGUI::Error::ObjectNotFound")) {
# choose another address cuz we've got a problem
$self->update({shippingAddressId=>''});
}
# if there is no shipping address we can't check out
if (WebGUI::Error->caught) {
$var{shippingPrice} = $var{tax} = $self->formatCurrency(0);
}
# if there is a shipping address calculate tax and shipping options
else {
$var{hasShippingAddress} = 1;
$var{shippingAddress} = $address->getHtmlFormatted;
my $ship = WebGUI::Shop::Ship->new(session => $self->session);
$var{items} = \@items;
if ($var{shippableItemsInCart}) {
my $ship = WebGUI::Shop::Ship->new($self->session);
my $options = $ship->getOptions($self);
my $numberOfOptions = scalar keys %{ $options };
if ($numberOfOptions < 1) {
if (! $numberOfOptions) {
$var{shippingOptions} = '';
$var{shippingPrice} = 0;
$error{id $self} = $i18n->get("No shipping plugins configured");
}
elsif ($numberOfOptions == 1) {
my ($option) = keys %{ $options };
$self->update({ shipperId => $option });
$var{shippingPrice} = $options->{$self->get("shipperId")}->{price};
$var{shippingPrice} = $self->formatCurrency($var{shippingPrice});
$self->error($i18n->get("No shipping plugins configured"));
}
else {
tie my %formOptions, 'Tie::IxHash';
$formOptions{''} = $i18n->get('Choose a shipping method');
foreach my $option (keys %{$options}) {
$formOptions{$option} = $options->{$option}{label}." (".$self->formatCurrency($options->{$option}{price}).")";
foreach my $optionId (keys %{$options}) {
$formOptions{$optionId} = $options->{$optionId}{label};
if ($options->{$optionId}->{hasPrice}) {
$formOptions{$optionId} .= ' ('.$self->formatCurrency($options->{$optionId}{price}).')';
}
}
$var{shippingOptions} = WebGUI::Form::selectBox($session, {name=>"shipperId", options=>\%formOptions, value=>$self->get("shipperId")});
if (!exists $options->{$self->get('shipperId')}) {
my $shipperId = $self->get('shipperId');
if (!$shipperId && $numberOfOptions == 1) {
my ($option) = keys %{ $options };
$self->update({shipperId => $option});
$shipperId = $option;
}
$var{shippingOptions} = WebGUI::Form::selectBox($session, {name=>"shipperId", options=>\%formOptions, value=>$shipperId || ''});
if (!exists $options->{$shipperId}) {
$self->update({shipperId => ''});
$shipperId = '';
}
if (my $shipperId = $self->get('shipperId')) {
if ($shipperId) {
$var{shippingPrice} = $options->{$shipperId}->{price};
}
else {
$var{shippingPrice} = 0;
$error{id $self} = ($i18n->get('Choose a shipping method and update the cart to checkout'));
$self->error($i18n->get('Choose a shipping method and update the cart to checkout'));
}
$var{shippingPrice} = $self->formatCurrency($var{shippingPrice});
$var{shippingPrice} = $shipperId && $options->{$shipperId}->{hasPrice} ? $self->formatCurrency($var{shippingPrice}) : '';
$var{tax} = $self->calculateTaxes;
}
}
else {
$var{shippingPrice} = $var{tax} = $self->formatCurrency(0);
}
# Tax variables
$var{tax} = $self->calculateTaxes;
#Address form variables
if ($var{userIsVisitor}) {
$var{loginFormHeader} = WebGUI::Form::formHeader($session, {action => $session->url->page})
. WebGUI::Form::hidden($session,{ name => 'op', value => 'auth'})
. WebGUI::Form::hidden($session,{ name => 'method', value => 'login'})
;
$var{loginFormUsername} = WebGUI::Form::text($session, { name => 'username', size => 12, });
$var{loginFormPassword} = WebGUI::Form::password($session, { name => 'identifier', size => 12, });
$var{loginFormButton} = WebGUI::Form::submit($session, { value => $i18n->get(52,'WebGUI'), });
$var{registerLink} = $session->url->page('op=auth;method=createAccount');
$session->scratch->set('redirectAfterLogin', $session->url->page('shop=cart'));
$var{loginFormFooter} = WebGUI::Form::formFooter($session)
}
else {
##Address form variables
tie my %billingAddressOptions, 'Tie::IxHash';
$billingAddressOptions{'new_address'} = $i18n->get('Add new address');
my $billingAddressId = $self->get('billingAddressId');
if ($billingAddressId) {
$billingAddressOptions{'update_address'} = $i18n->get('Update this address');
}
%billingAddressOptions = (%billingAddressOptions, %addressOptions);
$var{'billingAddressChooser'} = WebGUI::Form::selectBox($session, {
name => 'billingAddressId',
options => \%billingAddressOptions,
value => $billingAddressId ? $billingAddressId : 'new_address',
});
tie my %shippingAddressOptions, 'Tie::IxHash';
$shippingAddressOptions{'new_address'} = $i18n->get('Add new address');
my $shippingAddressId = $self->get('shippingAddressId');
if ($shippingAddressId) {
$shippingAddressOptions{'update_address'} = $i18n->get('Update this address');
}
%shippingAddressOptions = (%shippingAddressOptions, %addressOptions);
$var{'shippingAddressChooser'} = WebGUI::Form::selectBox($session, {
name => 'shippingAddressId',
options => \%shippingAddressOptions,
value => $shippingAddressId ? $shippingAddressId : 'new_address',
});
my $shippingAddressData = $self->get('shippingAddressId') ? $self->getShippingAddress->get() : {};
my $billingAddressData = $self->get('billingAddressId') ? $self->getBillingAddress->get() : {};
my $addressBook = $self->getAddressBook;
$addressBook->appendAddressFormVars(\%var, 'shipping_', $shippingAddressData);
$addressBook->appendAddressFormVars(\%var, 'billing_', $billingAddressData);
$var{sameShippingAsBilling} = WebGUI::Form::yesNo($session, {
name => 'sameShippingAsBilling',
value => $self->get('billingAddressId') && $self->get('billingAddressId') eq $self->get('shippingAddressId'),
});
}
# Payment methods
my $pay = WebGUI::Shop::Pay->new($session);
tie my %paymentOptions, 'Tie::IxHash';
$paymentOptions{''} = $i18n->get('Choose a payment method');
my $gateways = $pay->getOptions($self);
while (my ($gatewayId, $label) = each %{ $gateways }) {
$paymentOptions{$gatewayId} = $label;
}
$var{paymentOptions} = WebGUI::Form::selectBox($session, {
name => 'gatewayId',
options => \%paymentOptions,
value => $self->get('gatewayId') || $form->get('gatewayId') || '',
});
# POS variables
$var{isCashier} = WebGUI::Shop::Admin->new($session)->isCashier;
$var{isCashier} = WebGUI::Shop::Admin->new($session)->isCashier;
$var{posLookupForm} = WebGUI::Form::email($session, {name=>"posEmail"})
.WebGUI::Form::submit($session, {value=>$i18n->get('search for email'),
extras=>q|onclick="this.form.method.value='lookupPosUser';this.form.submit;"|});
my $posUser = $self->getPosUser;
my $posUser = $self->getPosUser;
$var{posUsername} = $posUser->username;
$var{posUserId} = $posUser->userId;
$var{posUserId} = $posUser->userId;
# calculate price adjusted for in-store credit
$var{totalPrice} = $var{subtotalPrice} + $var{shippingPrice} + $var{tax};
$var{subtotalPrice} = $self->formatCurrency($self->calculateSubtotal());
$var{totalPrice} = $var{subtotalPrice} + $var{shippingPrice} + $var{tax};
my $credit = WebGUI::Shop::Credit->new($session, $posUser->userId);
$var{ inShopCreditAvailable } = $credit->getSum;
$var{ inShopCreditDeduction } = $credit->calculateDeduction($var{totalPrice});
$var{ totalPrice } = $self->formatCurrency($var{totalPrice} + $var{inShopCreditDeduction});
$var{ readyForCheckout } = $self->readyForCheckout;
$var{ error } = $error{id $self};
foreach my $field (qw/subtotalPrice inShopCreditAvailable inShopCreditDeduction totalPrice shippingPrice tax/) {
$var{$field} = sprintf q|<span id="%sWrap">%s</span>|, $field, $var{$field};
}
$var{ error } = $self->error;
# render the cart
my $template = WebGUI::Asset::Template->newById($session, $session->setting->get("shopCartTemplateId"));
my $template = WebGUI::Asset->newById($session, $session->setting->get("shopCartTemplateId"));
my $style = $session->style;
my $yui = $url->extras('/yui/build');
$style->setScript("$yui/yahoo/yahoo-min.js");
$style->setScript("$yui/json/json-min.js");
$style->setScript("$yui/event/event-min.js");
$style->setScript("$yui/connection/connection-min.js");
$style->setScript($url->extras('underscore/underscore-min.js'));
$style->setScript($url->extras('shop/cart.js'), undef, 1);
return $session->style->userStyle($template->process(\%var));
}

View file

@ -130,9 +130,9 @@ sub getDrivers {
=head2 getOptions ( $cart )
Returns a set of options for the user to pay to. It is a hash of
hashrefs, with the key of the primary hash being the paymentGatewayId
of the driver, and sub keys of label and button. The hash will only
contain payment gateways that this user is allowed to use.
gatewayIds and labels.
The hash will only contain payment gateways that this user is allowed to use.
=head3 $cart
@ -146,17 +146,13 @@ sub getOptions {
WebGUI::Error::InvalidParam->throw(error => q{Need a cart.}) unless defined $cart and $cart->isa("WebGUI::Shop::Cart");
my $session = $cart->session;
my $recurringRequired = $cart->requiresRecurringPayment;
my %options = ();
foreach my $gateway (@{ $self->getPaymentGateways() }) {
next unless $gateway->canUse;
if (!$recurringRequired || $gateway->handlesRecurring) {
$options{$gateway->getId} = {
label => $gateway->get("label"),
button => $gateway->getButton( $cart ),
};
$options{$gateway->getId} = $gateway->get("label");
}
}
return \%options;
@ -366,68 +362,4 @@ sub www_manage {
return $console->render($output, $i18n->get("payment methods"));
}
#-------------------------------------------------------------------
=head2 www_selectPaymentGateway ( )
The screen in which a customer chooses a payment gateway.
TODO: Template this screen.
=cut
sub www_selectPaymentGateway {
my $self = shift;
my $session = $self->session;
my $cart = WebGUI::Shop::Cart->newBySession( $session );
my $i18n = WebGUI::International->new( $session, 'Shop' );
# Make sure the user is logged in.
if ($session->user->isVisitor) {
$session->scratch->set( 'redirectAfterLogin', $session->url->page('shop=pay;method=selectPaymentGateway') );
# We cannot use WebGUI::Operation::execute( $session, 'auth'); because the method form param used by the
# Shop contenthandler overrides the method param used by WG::Op::Auth
$session->http->setRedirect( $session->url->page('op=auth;method=init') );
# If the redirect fails make sure people can still go to the login screen by giving them a link
return $session->style->userStyle(
sprintf $i18n->get('login message'), $session->url->page('op=auth;method=init')
);
}
# Check if the cart is ready for checkout
unless ($cart->readyForCheckout) {
$session->http->setRedirect( $session->url->page('shop=cart;method=view') );
return '';
}
# Complete Transaction if it's a $0 transaction.
my $total = $cart->calculateTotal;
if (sprintf('%.2f', $total + $cart->calculateShopCreditDeduction($total)) eq '0.00') {
my $transaction = WebGUI::Shop::Transaction->create($session, {cart => $cart});
$transaction->completePurchase('zero', 'success', 'success');
$cart->onCompletePurchase;
$transaction->sendNotifications();
return $transaction->thankYou();
}
# All the output stuff below is just a placeholder until it's templated.
my $payOptions = $self->getOptions( $cart );
# TODO: If only one payOption exists, just send us there
# In order to do this, the PayDriver must give us a direct URL to go to
my $var;
my @paymentGateways;
foreach my $payOption ( values %{$payOptions} ) {
push @paymentGateways, $payOption;
}
$var->{ paymentGateways } = \@paymentGateways;
$var->{ choose } = $i18n->get('choose payment gateway message');
my $template = WebGUI::Asset::Template->newById($session, $session->setting->get("selectGatewayTemplateId"));
return $session->style->userStyle($template->process($var));
}
1;

View file

@ -80,6 +80,33 @@ sub _buildObj {
}
#-------------------------------------------------------------------
=head2 appendCartVariables ( $var )
Append the subtotal, shipping, tax, and shop credeductions to a set of template
variables.
=cut
sub appendCartVariables {
my ($self, $var) = @_;
$var ||= {};
my $cart = $self->getCart;
$var->{shippableItemsInCart} = $cart->requiresShipping;
$var->{subtotal} = $cart->calculateSubtotal;
$var->{shipping} = $cart->calculateShipping;
$var->{taxes} = $cart->calculateTaxes;
my $totalPrice = $var->{subtotal} + $var->{shipping} + $var->{taxes};
my $session = $self->session;
my $credit = WebGUI::Shop::Credit->new($session, $cart->getPosUser->userId);
$var->{inShopCreditAvailable} = $credit->getSum;
$var->{inShopCreditDeduction} = $credit->calculateDeduction($var->{totalPrice});
$var->{totalPrice } = $cart->formatCurrency($totalPrice + $var->{inShopCreditDeduction});
return $self;
}
#-------------------------------------------------------------------
=head2 cancelRecurringPayment ( transaction )
@ -340,12 +367,13 @@ sub getAddress {
=head2 getButton ( )
Returns the form that will take the user to check out.
Used for the generic, vanilla checkout form. Must be overridden by any methods that
use the default www_getCredentials.
=cut
sub getButton {
my $self = shift;
return '';
}
#-------------------------------------------------------------------
@ -358,9 +386,7 @@ Returns the WebGUI::Shop::Cart object for the current session.
sub getCart {
my $self = shift;
my $cart = WebGUI::Shop::Cart->newBySession( $self->session );
return $cart;
}
@ -463,51 +489,6 @@ sub getName {
#-------------------------------------------------------------------
=head2 getSelectAddressButton ( returnMethod, [ buttonLabel ] )
Generates a button for selecting an address.
=head3 returnMethod
The name of the www_ method the selected addressId should be returned to. Without the 'www_' part.
=head3 buttonLabel
The label for the button, defaults to the internationalized version of 'Choose billing address'.
=cut
sub getSelectAddressButton {
my $self = shift;
my $returnMethod = shift;
my $buttonLabel = shift || 'Choose billing address';
my $session = $self->session;
# Generate the json string that defines where the address book posts the selected address
my $callbackParams = {
url => $session->url->page,
params => [
{ name => 'shop', value => 'pay' },
{ name => 'method', value => 'do' },
{ name => 'do', value => $returnMethod },
{ name => 'paymentGatewayId', value => $self->getId },
],
};
my $callbackJson = JSON::to_json( $callbackParams );
# Generate 'Choose billing address' button
my $addressButton = WebGUI::Form::formHeader( $session )
. WebGUI::Form::hidden( $session, { name => 'shop', value => 'address' } )
. WebGUI::Form::hidden( $session, { name => 'method', value => 'view' } )
. WebGUI::Form::hidden( $session, { name => 'callback', value => $callbackJson } )
. WebGUI::Form::submit( $session, { value => $buttonLabel } )
. WebGUI::Form::formFooter( $session );
return $addressButton;
}
#-------------------------------------------------------------------
=head2 handlesRecurring ()
Returns 0. Should be overridden to return 1 by any subclasses that can handle recurring payments.
@ -581,6 +562,35 @@ sub processPayment {
=head2 processPropertiesFromFormPost ( )
Updates pay driver with data from Form.
=cut
sub processTemplate {
my $self = shift;
my $session = $self->session;
my $templateId = shift;
my $var = shift;
my $i18n = WebGUI::International->new($session, 'PayDriver');
my $template = eval { WebGUI::Asset->newById($session, $templateId); };
my $output;
if (!Exception::Class->caught) {
$template->prepare;
$output = $template->process($var);
}
else {
$output = $i18n->get('template gone');
}
return $output;
}
#-------------------------------------------------------------------
=head2 processPropertiesFromFormPost ( )
Updates ship driver with data from Form.
=cut
@ -637,7 +647,6 @@ sub processTransaction {
my $transactionProperties;
$transactionProperties->{ paymentMethod } = $self;
$transactionProperties->{ cart } = $cart;
$transactionProperties->{ paymentAddress } = $paymentAddress if defined $paymentAddress;
$transactionProperties->{ isRecurring } = $cart->requiresRecurringPayment;
# Create a transaction...
@ -708,6 +717,31 @@ a GUID.
#-------------------------------------------------------------------
=head2 www_getCredentials ( )
Displays a summary of the cart, and a button to checkout. Plugins that need to get additional
information, or perform additional checks, should override this method. Uses the getButton
method to create the checkout button.
=cut
sub www_getCredentials {
my ($self) = @_;
my $session = $self->session;
# Generate 'Proceed' button
my $i18n = WebGUI::International->new($session, 'PayDriver_Cash');
my $var = {
proceedButton => $self->getButton,
};
$self->appendCartVariables($var);
my $output = $self->processTemplate($self->get("summaryTemplateId"), $var);
return $session->style->userStyle($output);
}
#-------------------------------------------------------------------
=head2 www_edit ( )
Generates an edit form.

View file

@ -56,6 +56,15 @@ sub definition {
my $i18n = WebGUI::International->new($session, 'PayDriver_Cash');
tie my %fields, 'Tie::IxHash';
%fields = (
summaryTemplateId => {
fieldType => 'template',
label => $i18n->get('summary template'),
hoverHelp => $i18n->get('summary template help'),
namespace => 'Shop/Credentials',
defaultValue => '30h5rHxzE_Q0CyI3Gg7EJw',
},
);
push @{ $definition }, {
name => $i18n->get('label'),
@ -69,21 +78,21 @@ sub definition {
=head2 getButton ( )
Returns the HTML for a form containing a button that, when clicked, will take the user to the checkout screen of
this plugin.
Return a form with button to finalize checkout from the Shop.
=cut
sub getButton {
my $self = shift;
my ($self) = @_;
my $session = $self->session;
my $payForm = WebGUI::Form::formHeader($session)
. $self->getDoFormTags('getCredentials')
. WebGUI::Form::submit($session, {value => $self->get('label') })
. WebGUI::Form::formFooter($session);
return $payForm;
# Generate 'Proceed' button
my $i18n = WebGUI::International->new($session, 'PayDriver_Cash');
return WebGUI::Form::formHeader( $session )
. $self->getDoFormTags('pay')
. WebGUI::Form::submit( $session, { value => $i18n->get('Pay') } )
. WebGUI::Form::formFooter( $session)
;
}
#-------------------------------------------------------------------
@ -100,64 +109,6 @@ sub processPayment {
#-------------------------------------------------------------------
=head2 www_getCredentials ( [ addressId ] )
Displays the checkout form for this plugin.
=head3 addressId
Optionally supply this variable which will set the payment address to this addressId.
=cut
sub www_getCredentials {
my ($self, $addressId) = @_;
my $session = $self->session;
# Process address from address book if passed
$addressId = $session->form->process( 'addressId' );
my $address;
if ( $addressId ) {
$address = eval{ $self->getAddress( $addressId ) };
}
else {
$address = $self->getCart->getShippingAddress;
}
my $billingAddressHtml = $address->getHtmlFormatted;
# Generate the json string that defines where the address book posts the selected address
my $callbackParams = {
url => $session->url->page,
params => [
{ name => 'shop', value => 'pay' },
{ name => 'method', value => 'do' },
{ name => 'do', value => 'setBillingAddress' },
{ name => 'paymentGatewayId', value => $self->getId },
],
};
my $callbackJson = JSON::to_json( $callbackParams );
# Generate 'Choose billing address' button
my $addressButton = WebGUI::Form::formHeader( $session )
. WebGUI::Form::hidden( $session, { name => 'shop', value => 'address' } )
. WebGUI::Form::hidden( $session, { name => 'method', value => 'view' } )
. WebGUI::Form::hidden( $session, { name => 'callback', value => $callbackJson } )
. WebGUI::Form::submit( $session, { value => 'Choose billing address' } )
. WebGUI::Form::formFooter( $session);
# Generate 'Proceed' button
my $proceedButton = WebGUI::Form::formHeader( $session )
. $self->getDoFormTags('pay')
. WebGUI::Form::hidden($session, {name=>"addressId", value=>$address->getId})
. WebGUI::Form::submit( $session, { value => 'Pay' } )
. WebGUI::Form::formFooter( $session);
return $session->style->userStyle($addressButton.'<br />'.$billingAddressHtml.'<br />'.$proceedButton);
}
#-------------------------------------------------------------------
=head2 www_pay ( )
Checks credentials, and completes the transaction if those are correct.
@ -166,36 +117,14 @@ Checks credentials, and completes the transaction if those are correct.
sub www_pay {
my $self = shift;
my $session = $self->session;
my $cart = $self->getCart;
my $i18n = WebGUI::International->new($session, 'PayDriver_Cash');
my $var;
# Make sure we can checkout the cart
return "" unless $self->canCheckoutCart;
# Make sure all required credentials have been supplied
my $billingAddress = $self->getAddress( $session->form->process('addressId') );
return $self->www_getCredentials unless $billingAddress;
# Complete the transaction
my $transaction = $self->processTransaction( $billingAddress );
my $transaction = $self->processTransaction( );
return $transaction->thankYou();
}
#-------------------------------------------------------------------
=head2 www_setBillingAddress {
Stores the selected billing address in this instance.
=cut
sub www_setBillingAddress {
my $self = shift;
my $session = $self->session;
return $self->www_getCredentials($session->form->process('addressId'));
}
1;

View file

@ -61,7 +61,7 @@ sub _generatePaymentRequestXML {
my $self = shift;
my $transaction = shift;
my $session = $self->session;
my $paymentAddress = $self->{ _billingAddress };
my $paymentAddress = $self->getCart->getBillingAddress->get();
my $cardData = $self->{ _cardData };
# Set up the XML.
@ -472,27 +472,6 @@ sub doXmlRequest {
#-------------------------------------------------------------------
=head2 getButton
Return a form to select this payment driver and to accept credentials from those
who wish to use it.
=cut
sub getButton {
my $self = shift;
my $session = $self->session;
my $payForm = WebGUI::Form::formHeader($session)
. $self->getDoFormTags('getCredentials')
. WebGUI::Form::submit($session, {value => $self->get('label') })
. WebGUI::Form::formFooter($session);
return $payForm;
}
#-------------------------------------------------------------------
=head2 handlesRecurring
Tells the commerce system that this payment plugin can handle recurring payments.
@ -519,19 +498,6 @@ sub processCredentials {
my $i18n = WebGUI::International->new($session,'PayDriver_ITransact');
my @error;
# Check address data
push @error, $i18n->get( 'invalid firstName' ) unless $form->process( 'firstName' );
push @error, $i18n->get( 'invalid lastName' ) unless $form->process( 'lastName' );
push @error, $i18n->get( 'invalid address' ) unless $form->process( 'address' );
push @error, $i18n->get( 'invalid city' ) unless $form->process( 'city' );
push @error, $i18n->get( 'invalid email' ) unless $form->email ( 'email' );
push @error, $i18n->get( 'invalid zip' )
if ( !$form->zipcode( 'zipcode' ) && $form->process( 'country' ) eq 'United States' );
# Check credit card data
push @error, $i18n->get( 'invalid card number' ) unless $form->integer('cardNumber');
push @error, $i18n->get( 'invalid cvv2' ) if ($self->get('useCVV2') && !$form->integer('cvv2'));
# Check if expDate and expYear have sane values
my ($currentYear, $currentMonth) = $self->session->datetime->localtime;
my $expires = $form->integer( 'expYear' ) . sprintf '%02d', $form->integer( 'expMonth' );
@ -549,66 +515,11 @@ sub processCredentials {
cvv2 => $form->integer( 'cvv2' ),
};
$self->{ _billingAddress } = {
address1 => $form->process( 'address' ),
code => $form->zipcode( 'zipcode' ),
city => $form->process( 'city' ),
firstName => $form->process( 'firstName' ),
lastName => $form->process( 'lastName' ),
email => $form->email ( 'email' ),
state => $form->process( 'state' ),
country => $form->process( 'country' ),
phoneNumber => $form->process( 'phone' ),
};
return;
}
#-------------------------------------------------------------------
=head2 getBillingAddress ( $addressId )
The billing address is not handled by WebGUI::Shop::Address, it comes from
www_getCredentials. However, WebGUI::Shop::Transaction requires an
WebGUI::Shop::Address object. The billing address is seeded with information
from the shipping address. If this address info is different, then create
a new address to hand to Transaction.
=head3 $addressId
The id of a WebGUI::Shop::Address. If not present, then use the shipping
address instead.
=cut
sub getBillingAddress {
my ($self, $addressId) = @_;
my $address = $addressId
? $self->getAddress( $addressId )
: $self->getCart->getShippingAddress
;
##If the user made any changes to the default address, create a new billing address
##and use it instead
if( $address->get('firstName' ) ne $self->{_billingAddress}->{ 'firstName' }
|| $address->get('lastName' ) ne $self->{_billingAddress}->{ 'lastName' }
|| $address->get('address1' ) ne $self->{_billingAddress}->{ 'address1' }
|| $address->get('city' ) ne $self->{_billingAddress}->{ 'city' }
|| $address->get('state' ) ne $self->{_billingAddress}->{ 'state' }
|| $address->get('code' ) ne $self->{_billingAddress}->{ 'code' }
|| $address->get('country' ) ne $self->{_billingAddress}->{ 'country' }
|| $address->get('phoneNumber' ) ne $self->{_billingAddress}->{ 'phoneNumber' }
|| $address->get('email' ) ne $self->{_billingAddress}->{ 'email' }
) {
my $billingAddress = $self->getCart->getAddressBook->addAddress( $self->{_billingAddress} );
return $billingAddress;
}
return $address;
}
#-------------------------------------------------------------------
=head2 processPayment ($transaction)
Contact ITransact and submit the payment data to them for processing.
@ -725,18 +636,7 @@ sub www_getCredentials {
my $session = $self->session;
my $form = $session->form;
my $i18n = WebGUI::International->new($self->session, 'PayDriver_ITransact');
my $u = WebGUI::User->new($self->session,$self->session->user->userId);
# Process address from address book if passed
my $addressId = $session->form->process( 'addressId' );
my $addressData;
if ( $addressId ) {
$addressData = eval{ $self->getAddress( $addressId )->get() } || {};
}
else {
$addressData = $self->getCart->getShippingAddress->get;
}
my $var = {};
# Process form errors
@ -748,55 +648,11 @@ sub www_getCredentials {
}
}
$var->{getSelectAddressButton} = $self->getSelectAddressButton( 'getCredentials' );
$var->{formHeader} = WebGUI::Form::formHeader($session)
. $self->getDoFormTags('pay');
if ($var->{formHeader}) {
$var->{formHeader} .= WebGUI::Form::hidden($session, {name => 'addressId', value => $addressId});
}
$var->{formFooter} = WebGUI::Form::formFooter();
# Address data form
$var->{firstNameField} = WebGUI::Form::text($session, {
name => 'firstName',
value => $form->process("firstName") || $addressData->{ "firstName" } || $u->profileField('firstName'),
});
$var->{lastNameField} = WebGUI::Form::text($session, {
name => 'lastName',
value => $form->process("lastName") || $addressData->{ "lastName" } || $u->profileField('lastName'),
});
$var->{addressField} = WebGUI::Form::text($session, {
name => 'address',
value => $form->process("address") || $addressData->{ address1 } || $u->profileField('homeAddress'),
});
$var->{cityField} = WebGUI::Form::text($session, {
name => 'city',
value => $form->process("city") || $addressData->{ city } || $u->profileField('homeCity'),
});
$var->{stateField} = WebGUI::Form::text($session, {
name => 'state',
value => $form->process("state") || $addressData->{ state } || $u->profileField('homeState'),
});
$var->{codeField} = WebGUI::Form::zipcode($session, {
name => 'zipcode',
value => $form->process("zipcode") || $addressData->{ code } || $u->profileField('homeZip'),
});
$var->{countryField} = WebGUI::Form::country($session, {
name => 'country',
value => ($form->process("country",'country', '') || $addressData->{ country } || $u->profileField("homeCountry") || 'United States of A'),
});
$var->{phoneField} = WebGUI::Form::phone($session, {
name => 'phone',
value => $form->process("phone",'phone') || $addressData->{ phoneNumber } || $u->profileField("homePhone"),
});
$var->{emailField} = WebGUI::Form::email($session, {
name => 'email',
value => $form->process('email', 'email') || $addressData->{ email } || $u->profileField('email'),
});
# Credit card information
$var->{cardNumberField} = WebGUI::Form::text($session, {
name => 'cardNumber',
@ -814,17 +670,9 @@ sub www_getCredentials {
value => $i18n->get('checkout button', 'Shop'),
extras => 'onclick="this.disabled=true;this.form.submit(); return false;"',
});
$self->appendCartVariables($var);
my $template = eval { WebGUI::Asset::Template->newById($session, $self->get("credentialsTemplateId")); };
my $output;
if (! Exception::Class->caught()) {
$template->prepare;
$output = $template->process($var);
}
else {
$output = $i18n->get('template gone');
}
my $output = $self->processTemplate($self->get("credentialsTemplateId"), $var);
return $session->style->userStyle($output);
}
@ -847,16 +695,8 @@ sub www_pay {
# Go back to checkout form if credentials are not ok
return $self->www_getCredentials( $credentialsErrors ) if $credentialsErrors;
my $addressId = $session->form->process( 'addressId' );
my $billingAddress = $self->getBillingAddress($addressId);
# Payment time!
my $transaction = $self->processTransaction( $billingAddress );
## The billing address object is temporary, just to send to the transaction.
## Delete it if we don't need it.
if ($billingAddress->getId ne $addressId) {
$billingAddress->delete;
}
my $transaction = $self->processTransaction( );
if ($transaction->get('isSuccessful')) {
return $transaction->thankYou();
}

View file

@ -102,6 +102,13 @@ sub definition {
hoverHelp => $i18n->get('use test mode help'),
defaultValue => 1,
},
summaryTemplateId => {
fieldType => 'template',
label => $i18n->get('summary template'),
hoverHelp => $i18n->get('summary template help'),
namespace => 'Shop/Credentials',
defaultValue => 'jysVZeUR0Bx2NfrKs5sulg',
},
);
push @{ $definition }, {
@ -114,28 +121,6 @@ sub definition {
#-------------------------------------------------------------------
=head2 getButton ( )
Returns the HTML for a form containing a button that, when clicked, will take the user to the checkout screen of
this plugin.
=cut
sub getButton {
my $self = shift;
my $session = $self->session;
my $i18n = WebGUI::International->new($session, 'PayDriver_Ogone');
my $payForm = WebGUI::Form::formHeader($session)
. $self->getDoFormTags('getCredentials')
. WebGUI::Form::submit($session, {value => $i18n->get('Ogone') })
. WebGUI::Form::formFooter($session);
return $payForm;
}
#-------------------------------------------------------------------
=head2 getCart
Returns the cart for either the current user or the transaction passed back by Ogone.
@ -273,80 +258,6 @@ sub ogoneCheckoutButton {
#-------------------------------------------------------------------
=head2 www_getCredentials ( [ addressId ] )
Displays the checkout form for this plugin.
=head3 addressId
Optionally supply this variable which will set the payment address to this addressId.
=cut
sub www_getCredentials {
my ($self, $addressId) = @_;
my $session = $self->session;
my $i18n = WebGUI::International->new( $session, 'PayDriver_Ogone' );
# Process address from address book if passed
$addressId = $session->form->process( 'addressId' );
my $address;
if ( $addressId ) {
$address = eval{ $self->getAddress( $addressId ) };
}
else {
$address = $self->getCart->getShippingAddress;
}
my $billingAddressHtml = $address->getHtmlFormatted;
# Fetch transaction
my $transactionId = $session->form->process('transactionId');
my $transaction;
if ($transactionId) {
$transaction = WebGUI::Shop::Transaction->new( $session, $transactionId );
}
# Or generate a new one
unless ($transaction) {
$transaction = $self->processTransaction( $address );
}
# Set the billing address
$transaction->update( {
paymentAddress => $address,
} );
# Generate the json string that defines where the address book posts the selected address
my $callbackParams = {
url => $session->url->page,
params => [
{ name => 'shop', value => 'pay' },
{ name => 'method', value => 'do' },
{ name => 'do', value => 'getCredentials' },
{ name => 'paymentGatewayId', value => $self->getId },
],
};
my $callbackJson = JSON::to_json( $callbackParams );
# Generate 'Choose billing address' button
my $addressButton = WebGUI::Form::formHeader( $session )
. WebGUI::Form::hidden( $session, { name => 'shop', value => 'address' } )
. WebGUI::Form::hidden( $session, { name => 'method', value => 'view' } )
. WebGUI::Form::hidden( $session, { name => 'callback', value => $callbackJson } )
. WebGUI::Form::submit( $session, { value => $i18n->get('choose billing address') } )
. WebGUI::Form::formFooter( $session);
# Generate 'Proceed' button
my $proceedButton = $address
? $self->ogoneCheckoutButton( $transaction, $address )
: $i18n->get('please choose a billing address')
;
return $session->style->userStyle($addressButton.'<br />'.$billingAddressHtml.'<br />'.$proceedButton);
}
#-------------------------------------------------------------------
=head2 checkPostbackSHA ( )
Processes the postback data Ogone sends after a payment/cancelation. Figures out which transaction the data belongs
@ -547,6 +458,40 @@ sub www_edit {
#-------------------------------------------------------------------
=head2 www_getCredentials ( )
Displays the checkout form for this plugin.
=cut
sub www_getCredentials {
my ($self) = @_;
my $session = $self->session;
# Fetch transaction
my $transactionId = $session->form->process('transactionId');
my $transaction;
if ($transactionId) {
$transaction = WebGUI::Shop::Transaction->new( $session, $transactionId );
}
# Or generate a new one
unless ($transaction) {
$transaction = $self->processTransaction( );
}
# Generate 'Proceed' button
my $var = {
proceedButton => $self->ogoneCheckoutButton,
};
$self->appendCartVariables($var);
my $output = $self->processTemplate($self->get("summaryTemplateId"), $var);
return $session->style->userStyle($output);
}
#-------------------------------------------------------------------
=head2 www_processTransaction ( )
This method is called by the post sale notfication.

View file

@ -339,4 +339,3 @@ sub getPaypalCountry {
}
1;

View file

@ -106,6 +106,14 @@ sub definition {
$fields{paypal}{defaultValue} = 'https://www.paypal.com/webscr';
$fields{api}{defaultValue} = 'https://api-3t.payPal.com/nvp';
$fields{summaryTemplateId} = {
fieldType => 'template',
label => $i18n->get('summary template'),
hoverHelp => $i18n->get('summary template help'),
namespace => 'Shop/Credentials',
defaultValue => 'GqnZPB0gLoZmqQzYFaq7bg',
},
push @{$definition}, {
name => $i18n->get('name'),
properties => \%fields,

View file

@ -123,6 +123,13 @@ sub definition {
hoverHelp => $i18n->get('button image help'),
defaultValue => '',
},
summaryTemplateId => {
fieldType => 'template',
label => $i18n->get('summary template'),
hoverHelp => $i18n->get('summary template help'),
namespace => 'Shop/Credentials',
defaultValue => '',
},
);
push @{$definition},
@ -164,7 +171,7 @@ sub getButton {
# do a submit button with i18n'd paypal text. If they did, we'll use an
# image submit.
my $button;
my $i18n = WebGUI::International->new( $session, 'PayDriver_PayPalStd' );
my $i18n = WebGUI::International->new( $session, 'PayDriver_PayPalStd' );
my $text = $i18n->get('PayPal');
if ( $self->get('buttonImage') ) {
my $raw = $self->get('buttonImage');
@ -329,5 +336,5 @@ sub www_completeTransaction {
: $self->displayPaymentError($transaction);
}
1;
1;

View file

@ -100,7 +100,14 @@ sub getDrivers {
=head2 getOptions ( $cart )
Returns a list of options for the user to ship, along with the cost of using each one. It is a hash of hashrefs,
with the key of the primary hash being the shipperId of the driver, and sub keys of label and price.
with the key of the primary hash being the shipperId of the driver, and sub keys of label, price, and whether the
price actually exists, to tell the difference between 0 and unknown.
{
label => 'ShipDriver label',
price => \d+,
hasPrice => 1 || 0,
}
=head3 $cart
@ -115,15 +122,24 @@ sub getOptions {
my %options = ();
SHIPPER: foreach my $shipper (@{$self->getShippers()}) {
next SHIPPER unless $shipper->get('enabled');
my $price = eval { $shipper->calculate($cart) };
if (my $e = WebGUI::Error->caught()) {
$self->session->log->warn($e->error);
next SHIPPER;
}
next SHIPPER unless $shipper->canUse;
my ($price, $hasPrice);
if ($cart->get('shippingAddressId')) {
$price = eval { $shipper->calculate($cart) };
if (my $e = WebGUI::Error->caught()) {
$self->session->log->warn($e->error);
next SHIPPER;
}
$hasPrice = 1;
}
else {
$price = 0;
$hasPrice = 0;
}
$options{$shipper->getId} = {
label => $shipper->get("label"),
price => $price,
label => $shipper->get("label"),
price => $price,
hasPrice => $hasPrice,
};
}
return \%options;

View file

@ -104,33 +104,6 @@ sub appendCartItemVars {
#-----------------------------------------------------------
=head2 appendCartVars ( var, cart )
Extend this method to add tax driver specific template variables to those supplied to the cart template.
=head3 var
The hash ref to add the template variables to.
=head3 cart
The instance of WebGUI::Shop::Cart to add the template variables for.
=cut
sub appendCartVars {
my $self = shift;
my $var = shift;
my $cart = shift;
WebGUI::Error::InvalidParam->throw( 'Must supply a hash ref' )
unless $var && ref $var eq 'HASH';
WebGUI::Error::InvalidObject->throw( expected => 'WebGUI::Shop::Cart', got => ref $cart, error => 'Must pass a cart' )
unless $cart && $cart->isa( 'WebGUI::Shop::Cart' );
}
#-----------------------------------------------------------
=head2 canManage ( )
Returns true if the current user can manage taxes.
@ -155,9 +128,9 @@ Returns the class name of your plugin. You must overload this method in you own
sub className {
my $self = shift;
$self->session->log->fatal( "Tax plugin ($self) is required to overload the className method" );
$self->session->log->fatal( "Tax plugin (".$self->className.") is required to overload the className method" );
return 'WebGUI::Shop:TaxDriver';
return 'WebGUI::Shop::TaxDriver';
}
#-----------------------------------------------------------

View file

@ -32,7 +32,7 @@ This package keeps records of every puchase made.
my $transaction = WebGUI::Shop::Transaction->new($session, $id);
# typical transaction goes like this:
my $transaction = WebGUI::Shop::Transaction->create({ cart=>$cart, paymentMethod=>$paymentMethod, paymentAddress=>$address});
my $transaction = WebGUI::Shop::Transaction->create({ cart=>$cart });
my ($transactionNumber, $status, $message) = $paymentMethod->tryTransaction;
if ($status eq "somekindofsuccess") {
$transaction->completePurchase($cart, $transactionNumber, $status, $message);
@ -744,44 +744,57 @@ sub update {
if (exists $newProperties->{cart}) {
my $cart = $newProperties->{cart};
$newProperties->{taxes} = $cart->calculateTaxes;
my $address = $cart->getShippingAddress;
$newProperties->{shippingAddressId} = $address->getId;
$newProperties->{shippingAddressName} = $address->get('firstName') . " " .$address->get('lastName');
$newProperties->{shippingAddress1} = $address->get('address1');
$newProperties->{shippingAddress2} = $address->get('address2');
$newProperties->{shippingAddress3} = $address->get('address3');
$newProperties->{shippingCity} = $address->get('city');
$newProperties->{shippingState} = $address->get('state');
$newProperties->{shippingCountry} = $address->get('country');
$newProperties->{shippingCode} = $address->get('code');
$newProperties->{shippingPhoneNumber} = $address->get('phoneNumber');
my $shipper = $cart->getShipper;
$newProperties->{shippingDriverId} = $shipper->getId;
$newProperties->{shippingDriverLabel} = $shipper->get('label');
$newProperties->{shippingPrice} = $shipper->calculate($cart);
$newProperties->{amount} = $cart->calculateTotal + $newProperties->{shopCreditDeduction};
my $billingAddress = $cart->getBillingAddress;
$newProperties->{paymentAddressId} = $billingAddress->getId;
$newProperties->{paymentAddressName} = $billingAddress->get('firstName') . " " . $billingAddress->get('lastName');
$newProperties->{paymentAddress1} = $billingAddress->get('address1');
$newProperties->{paymentAddress2} = $billingAddress->get('address2');
$newProperties->{paymentAddress3} = $billingAddress->get('address3');
$newProperties->{paymentCity} = $billingAddress->get('city');
$newProperties->{paymentState} = $billingAddress->get('state');
$newProperties->{paymentCountry} = $billingAddress->get('country');
$newProperties->{paymentCode} = $billingAddress->get('code');
$newProperties->{paymentPhoneNumber} = $billingAddress->get('phoneNumber');
my $shippingAddress = $cart->getShippingAddress;
$newProperties->{shippingAddressId} = $shippingAddress->getId;
$newProperties->{shippingAddressName} = $shippingAddress->get('firstName') . " " . $shippingAddress->get('lastName');
$newProperties->{shippingAddress1} = $shippingAddress->get('address1');
$newProperties->{shippingAddress2} = $shippingAddress->get('address2');
$newProperties->{shippingAddress3} = $shippingAddress->get('address3');
$newProperties->{shippingCity} = $shippingAddress->get('city');
$newProperties->{shippingState} = $shippingAddress->get('state');
$newProperties->{shippingCountry} = $shippingAddress->get('country');
$newProperties->{shippingCode} = $shippingAddress->get('code');
$newProperties->{shippingPhoneNumber} = $shippingAddress->get('phoneNumber');
if ($cart->requiresShipping) {
my $shipper = $cart->getShipper;
$newProperties->{shippingDriverId} = $shipper->getId;
$newProperties->{shippingDriverLabel} = $shipper->get('label');
$newProperties->{shippingPrice} = $shipper->calculate($cart);
}
else {
$newProperties->{shippingDriverLabel} = "NO SHIPPING";
$newProperties->{shippingPrice} = 0;
}
$newProperties->{amount} = $cart->calculateTotal + $newProperties->{shopCreditDeduction};
$newProperties->{shopCreditDeduction} = $cart->calculateShopCreditDeduction($newProperties->{amount});
$newProperties->{amount} += $newProperties->{shopCreditDeduction};
$newProperties->{amount} += $newProperties->{shopCreditDeduction};
my $pay = $cart->getPaymentGateway;
$newProperties->{paymentDriverId} = $pay->getId;
$newProperties->{paymentDriverLabel} = $pay->get('label');
foreach my $item (@{$cart->getItems}) {
$self->addItem({item=>$item});
}
}
if (exists $newProperties->{paymentAddress}) {
my $address = $newProperties->{paymentAddress};
$newProperties->{paymentAddressId} = $address->getId;
$newProperties->{paymentAddressName} = $address->get('firstName') ." ". $address->get('lastName');
$newProperties->{paymentAddress1} = $address->get('address1');
$newProperties->{paymentAddress2} = $address->get('address2');
$newProperties->{paymentAddress3} = $address->get('address3');
$newProperties->{paymentCity} = $address->get('city');
$newProperties->{paymentState} = $address->get('state');
$newProperties->{paymentCountry} = $address->get('country');
$newProperties->{paymentCode} = $address->get('code');
$newProperties->{paymentPhoneNumber} = $address->get('phoneNumber');
}
if (exists $newProperties->{paymentMethod}) {
my $pay = $newProperties->{paymentMethod};
$newProperties->{paymentDriverId} = $pay->getId;
$newProperties->{paymentDriverId} = $pay->getId;
$newProperties->{paymentDriverLabel} = $pay->get('label');
}
my @fields = (qw( isSuccessful transactionCode statusCode statusMessage amount shippingAddressId

384
lib/WebGUI/Wizard.pm Normal file
View file

@ -0,0 +1,384 @@
package WebGUI::Wizard;
use Scalar::Util qw(blessed);
use WebGUI::Form;
=head1 NAME
WebGUI::Wizard -- Generate wizards
=head1 SYNOPSIS
package MyWizard;
use base 'WebGUI::Wizard';
sub _get_steps { [qw( step1 )] }
# Show a form for the first step
sub www_step1 {
my ( $self ) = @_;
my $f = $self->getForm; # Get a WebGUI::HTMLForm
$f->text( name => "user" );
return $f->print;
}
# Process the form for the first step
sub www_step1Save {
my ( $self ) = @_;
if ( my $user = $self->session->form->get('user') ) {
$self->set({ 'user' => $user });
return;
}
else {
return "Must specify a user!";
}
}
# Override cleanup to provide a friendly message
sub www_cleanup {
my ( $self ) = @_;
$self->cleanup;
return "Thank you! " . $self->get('user');
}
=head1 DESCRIPTION
This class allows you to easily create reusable wizards that walk a user
through a step-by-step process to perform a task.
A user begins a Wizard by visiting ?op=wizard;wizard_class=MyWizard. Then
WebGUI shows the first step's form (in the synopsis above, step1 / www_step1 ).
Once the user completes the form, the www_step1Save subroutine is run. If an
error is returned, the user is shown the error and the same form again.
Otherwise, the wizard continues to the next step.
After all the steps in the wizard are complete, the wizard runs www_cleanup
to clean up after the wizard and return the user to their previous page.
All parameters gathered by the wizard are saved between page loads into
the user's session scratch. Only by finishing or restarting the wizard will
their progress be lost.
=head1 METHODS
=cut
#----------------------------------------------------------------------------
=head2 new ( session )
Create a new instance of a Wizard.
=cut
sub new {
my ( $class, $session ) = @_;
die "Require WebGUI::Session as first argument"
unless blessed( $session ) && $session->isa( 'WebGUI::Session' );
return bless { _session => $session, }, $class;
}
#----------------------------------------------------------------------------
=head2 _get_steps ( )
Return all the names of the steps involved in this wizard, in order. Steps may
be skipped and/or back-tracked to.
=cut
# OVERRIDE THIS!
sub _get_steps {
return [];
}
#----------------------------------------------------------------------------
=head2 canView ( )
Returns true if the current user is allowed to view this wizard. You should
override this.
=cut
sub canView {
return 1;
}
#----------------------------------------------------------------------------
=head2 cleanup ( )
Remove any leftovers after the wizard is finished
=cut
sub cleanup {
my ( $self ) = @_;
$self->session->scratch->delete( $self->getCacheKey );
return;
}
#----------------------------------------------------------------------------
=head2 dispatch ( )
Dispatch the request to the correct step(s). Thaw the user's params and freeze
them again after everything's done.
=cut
sub dispatch {
my ($self) = @_;
if ( !$self->canView ) {
return $self->session->privilege->noAccess;
}
# See if we process a form
if ( my $step = $self->getCurrentStep ) {
$self->session->log->info( "Processing " . $step );
# First fold in the new form bits
$self->thaw;
my $processSub = $self->can( 'www_' . $step . 'Save' );
my $errorMessage = $processSub->($self);
if ($errorMessage) {
$self->session->log->info( "Error in " . $step );
my $formSub = $self->can( 'www_' . $step );
return $self->wrapStyle( $errorMessage . $formSub->($self) );
}
else {
my $step = $self->getNextStep;
if ( $step ) {
# Not done, run the next step
$self->session->log->info( "Showing next step: " . $step );
$self->setCurrentStep( $step );
my $formSub = $self->can( 'www_' . $step );
my $output = $formSub->($self);
$self->freeze;
return $self->wrapStyle( $output );
}
else {
# We're done, run the cleanup
return $self->wrapStyle( $self->www_cleanup );
}
}
}
else {
# Starting over
$self->cleanup;
my $step = $self->_get_steps->[0];
$self->setCurrentStep( $step );
$self->session->log->info( "Starting wizard: " . $step );
my $formSub = $self->can( 'www_' . $step );
my $output = $formSub->($self);
$self->freeze;
return $self->wrapStyle( $output );
}
} ## end sub dispatch
#----------------------------------------------------------------------------
=head2 freeze ( )
Save the current params to long-term storage.
=cut
sub freeze {
my ( $self ) = @_;
$self->session->scratch->set( $self->getCacheKey, JSON->new->encode( $self->{_params} || {} ) );
}
#----------------------------------------------------------------------------
=head2 get ( [param] )
Get a hashref of params. If C<param> is specified, get only that specific param.
=cut
sub get {
my ( $self, $param ) = @_;
if ( $param ) {
return $self->{_params}->{$param};
}
return $self->{_params};
}
#----------------------------------------------------------------------------
=head2 getCacheKey ( )
Get the unique key to store the params under.
=cut
sub getCacheKey {
my ( $self ) = @_;
return "Wizard " . blessed( $self );
}
#----------------------------------------------------------------------------
=head2 getCurrentStep ( )
Get the name of the current step.
=cut
sub getCurrentStep {
my ( $self ) = @_;
if ( $self->{_step} ) {
return $self->{_step};
}
elsif ( $self->session->form->get('wizard_class') eq blessed($self) ) {
return $self->session->form->get('wizard_step');
}
return; # No step, so start at the beginning
}
#----------------------------------------------------------------------------
=head2 getForm ( [step] )
Get a WebGUI::HTMLForm object for a given step, defaulting to the current step.
=cut
sub getForm {
my ( $self, $step ) = @_;
$step ||= $self->getCurrentStep;
my $form = WebGUI::HTMLForm->new( $self->session,
action => $self->getStepUrl( $step ),
);
return $form;
}
#----------------------------------------------------------------------------
=head2 getNextStep ( )
Get the name of the next step
=cut
sub getNextStep {
my ( $self, $step ) = @_;
$step ||= $self->getCurrentStep;
for my $i ( 0 .. @{ $self->_get_steps } - 1 ) {
if ( $self->_get_steps->[$i] eq $step ) {
return $self->_get_steps->[ $i + 1 ];
}
}
}
#----------------------------------------------------------------------------
=head2 getStepUrl ( step )
Get the URL to go to a specific step. Only used when there is no processing
to do.
=cut
sub getStepUrl {
my ( $self, $step ) = @_;
return unless $step;
return $self->session->url->page(
'op=wizard;wizard_class=' . (blessed $self) . ';wizard_step=' . $step
);
}
#----------------------------------------------------------------------------
=head2 session ( )
Get the WebGUI::Session object
=cut
sub session {
return $_[0]->{_session};
}
#----------------------------------------------------------------------------
=head2 set ( params )
Set a hashref of params.
=cut
sub set {
my ( $self, $args ) = @_;
$self->{_params} = { %{$self->{_params}}, %$args };
return $self->{_params};
}
#----------------------------------------------------------------------------
=head2 setCurrentStep ( )
Set the current step. Useful before calling dispatch().
=cut
sub setCurrentStep {
my ( $self, $step ) = @_;
return $self->{_step} = $step;
}
#----------------------------------------------------------------------------
=head2 thaw ( )
Thaw the user's parameters from the long-term storage, overwriting any current
parameters.
=cut
sub thaw {
my ( $self ) = @_;
my $json = $self->session->scratch->get( $self->getCacheKey );
return $self->{_params} = $json ? JSON->new->decode( $json ) : {};
}
#----------------------------------------------------------------------------
=head2 wrapStyle ( output )
Wrap output in the Wizard style.
TODO: Add wizard-specific template vars like a progress bar and back links
=cut
sub wrapStyle {
my ( $self, $output ) = @_;
return $output;
}
#----------------------------------------------------------------------------
=head2 www_cleanup ( )
Clean up after the user, removing the variables, and return them to their
previous place.
NOTE: If you override this, you must remember to call C<cleanup> manually!
=cut
sub www_cleanup {
my ( $self ) = @_;
$self->cleanup;
$self->session->http->setRedirect( $self->session->url->page );
return "redirect";
}
1;

View file

@ -0,0 +1,427 @@
package WebGUI::Wizard::HomePage;
use strict;
use base 'WebGUI::Wizard';
=head1 NAME
WebGUI::Wizard::HomePage - Create or replace a Home Page with new content
=head1 DESCRIPTION
The HomePage wizard will create a new home page with a given style and with
the desired types of content.
=head1 METHODS
=cut
sub _get_steps {
return [ qw(
pickStyle
chooseContent
)
];
}
#-------------------------------------------------------------------
=head2 addAsset ( parent, properties )
A helper to add assets with less code.
=head3 parent
The parent asset to add to.
=head3 properties
A hash ref of properties to attach to the asset. One must be className.
=cut
sub addAsset {
my $parent = shift;
my $properties = shift;
$properties->{url} = $parent->get("url") . "/" . $properties->{title};
$properties->{groupIdEdit} = $parent->get("groupIdEdit");
$properties->{groupIdView} = $parent->get("groupIdView");
$properties->{ownerUserId} = $parent->get("ownerUserId");
$properties->{styleTemplateId} = $parent->get("styleTemplateId");
$properties->{printableStyleTemplateId} = $parent->get("styleTemplateId");
return $parent->addChild($properties);
}
#-------------------------------------------------------------------
=head2 addPage ( parent, title )
Adds a page to a parent page.
=head3 parent
A parent page asset.
=head3 title
The title of the new page.
=cut
sub addPage {
my $parent = shift;
my $title = shift;
return addAsset( $parent, { title => $title, className => "WebGUI::Asset::Wobject::Layout", displayTitle => 0 } );
}
#----------------------------------------------------------------------------
=head2 canView ( )
A user can view this wizard if they are an Admin
=cut
sub canView {
my ( $self ) = @_;
return $self->session->user->isAdmin;
}
#----------------------------------------------------------------------------
=head2 wrapStyle ( $output )
Wrap the output in the wizard style.
=cut
sub wrapStyle {
return WebGUI::Wizard::Setup::wrapStyle( @_ );
}
#----------------------------------------------------------------------------
=head2 www_pickStyle ( )
Choose the style for the new home page
=cut
sub www_pickStyle {
my ( $self ) = @_;
my $session = $self->session;
my $f = $self->getForm;
my $i18n = WebGUI::International->new( $session, "WebGUI" );
my $output = '<h1>' . $i18n->get('1073') . '</h1>';
my @styleIds
= $session->db->buildArray(
q{SELECT DISTINCT(assetId) FROM template WHERE namespace="style"}
);
# Verboten:
# PBtmpl0000000000000060
# PBtmpl0000000000000111
# PBtmpl0000000000000137
# PBtmpl0000000000000132
# Blank style:
# PBtmplBlankStyle000001
my @skipStyleIds = qw( PBtmpl0000000000000060 PBtmpl0000000000000111 PBtmpl0000000000000137
PBtmpl0000000000000132 PBtmplBlankStyle000001 );
# Instantiate the objects
my @styles;
for my $styleId ( @styleIds ) {
next if grep { $_ eq $styleId } @skipStyleIds;
my $style = WebGUI::Asset->newByDynamicClass( $session, $styleId );
push @styles, $style;
}
my $row = 0;
for my $style ( sort { $a->getTitle cmp $b->getTitle } @styles ) {
my $class = ++$row % 2 ? " odd" : "";
# Prepare the synopsis
my $synopsis = WebGUI::HTML::format( $style->get('synopsis') );
$synopsis =~ s{(https?://\S+)}{<a href="$1">$1</a>}g;
$f->raw(
'<div class="stylePicker' . $class . '"><label><input type="radio" name="styleTemplateId" value="' . $style->getId . '"/>'
. '<img src="' . $style->getExampleImageUrl . '" height="150" />'
. '<div class="title">' . $style->getTitle . '</div>'
. '<div class="synopsis">' . $synopsis . '</div></label>'
. '</div>'
);
}
$f->submit;
$output .= $f->print;
return $output . '<div style="clear: both;">&nbsp;</div>';
}
#----------------------------------------------------------------------------
=head2 www_pickStyleSave ( )
Store the style to use later when we create the content
=cut
sub www_pickStyleSave {
my ( $self ) = @_;
my $session = $self->session;
my ( $form ) = $session->quick(qw( form ));
# Coming from initial setup:
if ( $form->get('initialSetup') ) {
$self->set({ initialSetup => 1 });
}
$self->set({ "styleTemplateId", $form->get('styleTemplateId') });
return;
}
#----------------------------------------------------------------------------
=head2 www_chooseContent ( )
Choose and configure the content on the home page
=cut
sub www_chooseContent {
my ($self) = @_;
my $session = $self->session;
my $form = $session->form;
$session->http->setCacheControl("none");
my $i18n = WebGUI::International->new( $session, "WebGUI" );
my $output = '<h1>' . $i18n->get('Initial Pages') . '</h1>';
my $f = $self->getForm;
$f->yesNo( name => "contactUs", label => $i18n->get('Contact Us') );
$f->yesNo( name => "calendar", label => $i18n->get( "assetName", 'Asset_Calendar' ) );
$f->yesNo( name => "wiki", label => $i18n->get( 'assetName', 'Asset_WikiMaster' ) );
$f->yesNo( name => "search", label => $i18n->get( "assetName", 'Asset_Search' ) );
$f->yesNo( name => "aboutUs", label => $i18n->get("About Us") );
$f->HTMLArea(
name => "aboutUsContent",
richEditId => "PBrichedit000000000002",
value => $i18n->get("Put your about us content here.")
);
if ( exists $session->config->get('assets')->{"WebGUI::Asset::Wobject::Collaboration"} ) {
$f->yesNo( name => "news", label => $i18n->get(357) );
$f->yesNo( name => "forums", label => $i18n->get("Forums") );
$f->textarea(
name => "forumNames",
subtext => $i18n->get("One forum name per line"),
value => $i18n->get("Support") . "\n" . $i18n->get("General Discussion")
);
}
$f->submit;
$output .= $f->print;
return $output;
} ## end sub www_chooseContent
#----------------------------------------------------------------------------
=head2 www_chooseContentSave ( )
Create the new content with the correct style.
=cut
sub www_chooseContentSave {
my ($self) = @_;
my $session = $self->session;
my $form = $session->form;
my $i18n = WebGUI::International->new( $session, "WebGUI" );
my $home;
if ( $self->get('initialSetup') ) {
$home = WebGUI::Asset->getDefault($session);
}
else {
my $root = WebGUI::Asset->getRoot($session);
$home = addPage( $root, "New Home Page" );
}
# update default site style
$session->setting->set( "userFunctionStyleId", $self->get('styleTemplateId') );
foreach my $asset ( @{ $home->getLineage( [ "self", "descendants" ], { returnObjects => 1 } ) } ) {
if ( defined $asset ) {
$asset->update( { styleTemplateId => $self->get("styleTemplateId") } );
}
}
# add new pages
if ( $form->get("aboutUs") ) {
my $page = addPage( $home, $i18n->get("About Us") );
addAsset(
$page, {
title => $i18n->get("About Us"),
isHidden => 1,
className => "WebGUI::Asset::Wobject::Article",
description => $form->get("aboutUsContent"),
}
);
}
# add forums
if ( $form->get("forums") ) {
my $page = addPage( $home, $i18n->get("Forums") );
my $board = addAsset(
$page, {
title => $i18n->get("Forums"),
isHidden => 1,
className => "WebGUI::Asset::Wobject::MessageBoard",
description => $i18n->get("Discuss your ideas and get help from our community."),
}
);
my $forumNames = $form->get("forumNames");
$forumNames =~ s/\r//g;
foreach my $forumName ( split "\n", $forumNames ) {
next if $forumName eq "";
addAsset(
$board, {
title => $forumName,
isHidden => 1,
className => "WebGUI::Asset::Wobject::Collaboration"
}
);
}
} ## end if ( $form->get("forums"...))
# add news
if ( $form->get("news") ) {
my $page = addPage( $home, $i18n->get(357) );
addAsset(
$page, {
title => $i18n->get(357),
isHidden => 1,
className => "WebGUI::Asset::Wobject::Collaboration",
collaborationTemplateId => "PBtmpl0000000000000112",
allowReplies => 0,
attachmentsPerPost => 5,
postFormTemplateId => "PBtmpl0000000000000068",
threadTemplateId => "PBtmpl0000000000000067",
description => $i18n->get("All the news you need to know."),
}
);
} ## end if ( $form->get("news"...))
# add wiki
if ( $form->get("wiki") ) {
my $page = addPage( $home, $i18n->get( "assetName", 'Asset_WikiMaster' ) );
addAsset(
$page, {
title => $i18n->get( "assetName", 'Asset_WikiMaster' ),
isHidden => 1,
allowAttachments => 5,
className => "WebGUI::Asset::Wobject::WikiMaster",
description => $i18n->get("Welcome to our wiki. Here you can help us keep information up to date."),
}
);
}
# add calendar
if ( $form->get("calendar") ) {
my $page = addPage( $home, $i18n->get( 'assetName', "Asset_Calendar" ) );
addAsset(
$page, {
title => $i18n->get( 'assetName', "Asset_Calendar" ),
isHidden => 1,
className => "WebGUI::Asset::Wobject::Calendar",
description => $i18n->get("Check out what is going on."),
}
);
}
# add contact us
if ( $form->get("contactUs") ) {
my $page = addPage( $home, $i18n->get("Contact Us") );
my $i18n2 = WebGUI::International->new( $session, "Asset_DataForm" );
my @fieldConfig = ( {
name => "from",
label => $i18n2->get( "Your Email Address", 'WebGUI' ),
status => "required",
isMailField => 1,
width => 0,
type => "email",
}, {name => "to",
label => $i18n2->get(11),
status => "hidden",
isMailField => 1,
width => 0,
type => "email",
defaultValue => $session->setting->get("companyEmail"),
}, {name => "cc",
label => $i18n2->get(12),
status => "hidden",
isMailField => 1,
width => 0,
type => "email",
}, {name => "bcc",
label => $i18n2->get(13),
status => "hidden",
isMailField => 1,
width => 0,
type => "email",
}, {name => "subject",
label => $i18n2->get(14),
status => "hidden",
isMailField => 1,
width => 0,
type => "text",
defaultValue => $i18n->get(2),
}, {name => "comments",
label => $i18n->get( "comments", 'VersionTag' ),
status => "required",
type => "textarea",
subtext => $i18n->get("Tell us how we can assist you."),
},
);
my $dataForm = addAsset(
$page, {
title => $i18n->get("Contact Us"),
isHidden => 1,
className => "WebGUI::Asset::Wobject::DataForm",
description => $i18n->get("We welcome your feedback."),
acknowledgement =>
$i18n->get("Thanks for for your interest in ^c;. We will review your message shortly."),
mailData => 1,
fieldConfiguration => JSON->new->encode( \@fieldConfig ),
}
);
} ## end if ( $form->get("contactUs"...))
# add search
if ( $form->get("search") ) {
my $page = addPage( $home, $i18n->get( 'assetName', "Asset_Search" ) );
addAsset(
$page, {
title => $i18n->get( 'assetName', "Asset_Search" ),
isHidden => 1,
className => "WebGUI::Asset::Wobject::Search",
description => $i18n->get("Cannot find what you are looking for? Try our search."),
searchRoot => $home->getId,
}
);
}
# commit the working tag
my $working = WebGUI::VersionTag->getWorking($session);
$working->set( { name => "Home Page Wizard" } );
$working->commit;
return;
} ## end sub www_chooseContentSave
1;

416
lib/WebGUI/Wizard/Setup.pm Normal file
View file

@ -0,0 +1,416 @@
package WebGUI::Wizard::Setup;
use strict;
use base 'WebGUI::Wizard';
=head1 NAME
WebGUI::Wizard::Setup -- Initial site setup
=head1 DESCRIPTION
A WebGUI::Wizard to perform initial site setup tasks like defining the Admin
account, entering basic information, and choosing a default style.
=head1 METHODS
=cut
sub _get_steps {
return [qw(
adminAccount
companyInformation
siteStats
defaultStyle
)];
}
#----------------------------------------------------------------------------
=head2 canView ( )
A user can view this wizard if the site is newly created or if they are the
admin user
=cut
sub canView {
my ( $self ) = @_;
my $session = $self->session;
# Only specialState="init" or admin user
return $session->setting->get('specialState') eq 'init'
|| $session->user->getId eq '3';
}
#----------------------------------------------------------------------------
=head2 wrapStyle ( $output )
Wrap the output in the wizard style.
=cut
sub wrapStyle {
my ( $self, $output ) = @_;
my $session = $self->session;
my $form = $session->form;
$session->http->setCacheControl("none");
my $i18n = WebGUI::International->new( $session, "WebGUI" );
my $page = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>' . $i18n->get('WebGUI Initial Configuration') . '</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript">
function getWebguiProperty (propName) {
var props = new Array();
props["extrasURL"] = "' . $session->url->extras() . '";
props["pageURL"] = "' . $session->url->page( undef, undef, 1 ) . '";
return props[propName];
}
</script>
' . $session->style->generateAdditionalHeadTags . '
<style type="text/css">
body {
margin-top: 120px;
margin-left: 5%;
margin-right: 5%;
background-color: #ccf;
}
h1 {
position: absolute;
top: 10px;
padding: 0;
margin: 0;
padding-left: 120px;
background: url(' . $session->url->extras('wg.gif') . ') no-repeat;
line-height: 100px;
}
#wrapper {
background-color: white;
border: 1px solid black;
padding: 10px;
}
.stylePicker img {
margin: 1em 0;
float: right;
}
.stylePicker {
overflow: hidden;
clear: both;
}
.stylePicker.odd {
background-color: #eee;
}
.stylePicker input {
float: left;
}
.stylePicker .title {
font-size: larger;
}
</style>
</head>
<body><div id="wrapper"> ' . $output . ' </div></body>
</html>';
$session->http->setMimeType("text/html");
return $page;
}
#----------------------------------------------------------------------------
=head2 www_adminAccount ( )
Display the form to configure the admin account
=cut
sub www_adminAccount {
my ( $self ) = @_;
my $session = $self->session;
my $form = $session->form;
$session->http->setCacheControl("none");
my $i18n = WebGUI::International->new( $session, "WebGUI" );
my $legend = $i18n->get('admin account');
my $u = WebGUI::User->new( $session, '3' );
my $f = $self->getForm;
$f->text(
-name => "username",
-value => $u->username,
-label => $i18n->get(50),
-hoverHelp => $i18n->get('50 setup description'),
);
$f->text(
-name => "identifier",
-value => "123qwe",
-label => $i18n->get(51),
-hoverHelp => $i18n->get('51 description'),
-subtext => '<div style=\"font-size: 10px;\">(' . $i18n->get("password clear text") . ')</div>'
);
$f->email(
-name => "email",
-value => $u->profileField("email"),
-label => $i18n->get(56),
-hoverHelp => $i18n->get('56 description'),
);
$f->timeZone(
-name => "timeZone",
-value => $u->profileField("timeZone"),
-label => $i18n->get( 'timezone', 'DateTime' ),
-hoverHelp => $i18n->get('timezone help'),
);
$f->selectBox(
-name => "language",
-value => $u->profileField("language"),
-label => $i18n->get('304'),
-hoverHelp => $i18n->get('language help'),
-options => $i18n->getLanguages(),
);
$f->submit;
return '<h1>' . $legend . '</h1>' . $f->print;
}
#----------------------------------------------------------------------------
=head2 www_adminAccountSave ( )
Process the form and update the Admin account
=cut
sub www_adminAccountSave {
my ( $self ) = @_;
my $session = $self->session;
my $form = $session->form;
my $timezone = $form->timeZone("timeZone");
my $language = $form->selectBox("language");
##update Admin and Visitor users
my $u = WebGUI::User->new( $session, "3" );
$u->username( $form->process( "username", "text", "Admin" ) );
$u->profileField( "email", $form->email("email") );
$u->profileField( "timeZone", $timezone );
$u->profileField( "language", $language );
$u->identifier( Digest::MD5::md5_base64( $form->process( "identifier", "password", "123qwe" ) ) );
# The user is now Admin
$session->user({ userId => "3" });
$u = WebGUI::User->new( $session, "1" );
$u->profileField( "timeZone", $timezone );
$u->profileField( "language", $language );
##update ProfileField defaults so new users the get the defaults, too
my $properties;
my $zoneField = WebGUI::ProfileField->new( $session, 'timeZone' );
$properties = $zoneField->get();
$properties->{dataDefault} = $timezone;
$zoneField->set($properties);
my $languageField = WebGUI::ProfileField->new( $session, 'language' );
$properties = $languageField->get();
$properties->{dataDefault} = $language;
$languageField->set($properties);
return;
}
#----------------------------------------------------------------------------
=head2 www_companyInformation ( )
Enter basic company information
=cut
sub www_companyInformation {
my ( $self ) = @_;
my $session = $self->session;
my $form = $session->form;
$session->http->setCacheControl("none");
my $i18n = WebGUI::International->new( $session, "WebGUI" );
my $output = '<h1>' . $i18n->get('company information') . '</h1>';
my $f = $self->getForm;
$f->hidden( name => "step", value => "3" );
$f->text(
name => "companyName",
value => $session->setting->get("companyName"),
label => $i18n->get(125),
hoverHelp => $i18n->get('125 description'),
);
$f->email(
name => "companyEmail",
value => $session->setting->get("companyEmail"),
label => $i18n->get(126),
hoverHelp => $i18n->get('126 description'),
);
$f->url(
name => "companyURL",
value => $session->setting->get("companyURL"),
label => $i18n->get(127),
hoverHelp => $i18n->get('127 description'),
);
$f->submit;
$output .= $f->print;
return $output;
}
#----------------------------------------------------------------------------
=head2 www_companyInformationSave ( )
Update the company information
=cut
sub www_companyInformationSave {
my ( $self ) = @_;
my $session = $self->session;
my $form = $session->form;
$session->setting->set( 'companyName', $form->text("companyName") ) if ( $form->get("companyName") );
$session->setting->set( 'companyURL', $form->url("companyURL") ) if ( $form->get("companyURL") );
$session->setting->set( 'companyEmail', $form->email("companyEmail") ) if ( $form->get("companyEmail") );
return;
}
#----------------------------------------------------------------------------
=head2 www_siteStats ( )
Opt-in to the global WebGUI statistics
=cut
sub www_siteStats {
my ( $self ) = @_;
my $session = $self->session;
my $form = $session->form;
$session->http->setCacheControl("none");
my $i18n = WebGUI::International->new( $session, "WebGUI" );
my $enableForm = $self->getForm;
$enableForm->hidden( name => "enableStats", value => 1 );
$enableForm->submit( value => $i18n->get( 'enable', 'Activity_SendWebguiStats' ) );
my $disableForm = $self->getForm;
$disableForm->hidden( name => "enableStats", value => 0 );
$disableForm->submit( value => $i18n->get( 'disable', 'Activity_SendWebguiStats' ) );
my $output = '<h1>' . $i18n->get( 'topicName', 'Activity_SendWebguiStats' ) . '</h1>';
$output .= ' <p>' . $i18n->get( 'why to send', 'Activity_SendWebguiStats' ) . '</p>
<p>' . $i18n->get( 'would you participate', 'Activity_SendWebguiStats' ) . '</p>
<div style="float: left">' . $enableForm->print . '</div><div style="float: left">'
. $disableForm->print
. '</div>'
. '<div style="clear: both;">&nbsp;</div>'
;
return $output;
}
#----------------------------------------------------------------------------
=head2 www_siteStatsSave ( )
Opt-in to the global WebGUI statistics
=cut
sub www_siteStatsSave {
my ( $self ) = @_;
my $session = $self->session;
my $form = $session->form;
WebGUI::Operation::Statistics::www_enableSendWebguiStats($session) if ( $form->get("enableStats") );
return;
}
#----------------------------------------------------------------------------
=head2 www_defaultStyle ( )
Choose the default site style
=cut
sub www_defaultStyle {
return WebGUI::Wizard::HomePage::www_pickStyle( @_ );
}
#----------------------------------------------------------------------------
=head2 www_defaultStyleSave ( )
Save the default style to all existing pages and the user function style
=cut
sub www_defaultStyleSave {
my ( $self, @args ) = @_;
my $output = WebGUI::Wizard::HomePage::www_pickStyleSave( $self, @args );
my $session = $self->session;
# update default site style
$session->setting->set( "userFunctionStyleId", $self->get('styleTemplateId') );
my $home = WebGUI::Asset->getDefault( $session );
foreach my $asset ( @{ $home->getLineage( [ "self", "descendants" ], { returnObjects => 1 } ) } ) {
if ( defined $asset ) {
$asset->update( { styleTemplateId => $self->get("styleTemplateId") } );
}
}
return $output;
}
#----------------------------------------------------------------------------
=head2 www_cleanup ( )
Give the user a choice to do the Home Page wizard
=cut
sub www_cleanup {
my ( $self ) = @_;
my $session = $self->session;
my $form = $session->form;
$session->http->setCacheControl("none");
my $i18n = WebGUI::International->new( $session, "WebGUI" );
$self->cleanup;
# Delete specialState
$session->setting->remove( "specialState" );
my $starterForm = WebGUI::HTMLForm->new( $session );
$starterForm->hidden( name => "op", value => "wizard" );
$starterForm->hidden( name => "wizard_class", value => "WebGUI::Wizard::HomePage" );
$starterForm->hidden( name => "wizard_step", value => "pickStyle" );
$starterForm->hidden( name => "initialSetup", value => 1 );
$starterForm->hidden( name => "styleTemplateId", value => $self->get('styleTemplateId') );
$starterForm->submit( value => $i18n->get( 'yes please' ) );
my $output = '<h1>' . $i18n->get('site starter title') . '</h1>';
$output .= ' <p>' . $i18n->get('site starter body') . '</p>'
. '<div style="float: left">' . $starterForm->print . '</div>'
. sprintf(
'<div style="float: left"><a href="%s">%s</a></div>',
$session->url->gateway,
$i18n->get('no thanks'),
)
. '<div style="clear: both">&nbsp;</div>'
;
return $output;
}
1;

View file

@ -16,7 +16,7 @@ sub makeUrlCompliant {
$value =~ s/^\s+//; #removes leading whitespace
$value =~ s/ /-/g; #replaces whitespace with hyphens
$value =~ s/\.$//; #removes trailing period
$value =~ s/[^A-Za-z0-9\-\.\_\/]//g; #removes all funky characters
$value =~ s/[^\w\-\.\_\/]//g; #removes characters that would interfere with the url
$value =~ s/^\///; #removes a leading /
$value =~ s/\/$//; #removes a trailing /
$value =~ s/\/\//\//g; #removes double /

View file

@ -243,7 +243,7 @@ our $I18N = {
},
'form_fax' => {
message => "A text field for entering in a phone number.",
message => "A text field for entering in a fax number.",
lastUpdated => 0,
context => "template variable help",
},

View file

@ -390,6 +390,16 @@ Any scratch variables will be available in the template with this syntax:<br/>
lastUpdated => 0,
},
'field storageIdExample' => {
message => 'Example Image',
lastUpdated => 0,
},
'field storageIdExample description' => {
message => 'An example image to show what the template looks like before the user selects it',
lastUpdated => 0,
},
};
1;

View file

@ -537,7 +537,7 @@ listing of pages that are related to a specific keyword?| },
},
'keywords_loop' => {
message => q{A loop containing all the top level keywords, links to their keyword pages, and all sub pages below them.},
message => q{A loop containing all the top level keywords for this page, links to their keyword pages, and all sub pages below them.},
lastUpdated => 0,
context => q{Help for template variable},
},
@ -560,6 +560,12 @@ listing of pages that are related to a specific keyword?| },
context => q{Help for template variable},
},
'keyword descendants' => {
message => q{The number of wiki pages that are tagged with this keyword, and all sub-keywords of this keyword.},
lastUpdated => 0,
context => q{Help for template variable},
},
'indent_loop' => {
message => q{A loop that runs 1 time for each level.},
lastUpdated => 0,
@ -572,6 +578,84 @@ listing of pages that are related to a specific keyword?| },
context => q{Help for template variable},
},
'by keyword template title' => {
message => q{Wiki By Keyword Template Variables},
lastUpdated => 0,
context => q{Help for template variable},
},
'by keyword keyword' => {
message => q{The keyword that was requested.},
lastUpdated => 0,
context => q{Help for template variable},
},
'by keyword pagesLoop' => {
message => q{A loop of pages that contain the requested keyword.},
lastUpdated => 0,
context => q{Help for template variable},
},
'by keyword title' => {
message => q{The title of this page in the loop.},
lastUpdated => 0,
context => q{Help for template variable},
},
'by keyword url' => {
message => q{The url of this page in the loop.},
lastUpdated => 0,
context => q{Help for template variable},
},
'by keyword synopsis' => {
message => q{The synopsis of this page in the loop.},
lastUpdated => 0,
context => q{Help for template variable},
},
'by keyword formHeader' => {
message => q{HTML code to start the form for entering in sub-keywords. This will be empty unless the current user can administer this wiki},
lastUpdated => 0,
context => q{Help for template variable},
},
'by keyword formFooter' => {
message => q{HTML code to end the form for entering in sub-keywords. This will be empty unless the current user can administer this wiki},
lastUpdated => 0,
context => q{Help for template variable},
},
'by keyword keywordForm' => {
message => q{HTML code for the field for entering in sub-keywords. This will be empty unless the current user can administer this wiki},
lastUpdated => 0,
context => q{Help for template variable},
},
'by keyword submitForm' => {
message => q{A button to submit the sub-keywords form.},
lastUpdated => 0,
context => q{Help for template variable},
},
'Related Pages' => {
message => q{Related Pages},
lastUpdated => 0,
context => q{template label},
},
'keyword page variables' => {
message => q{Keyword Page Variables},
lastUpdated => 0,
context => q{template variable help},
},
'keyword isTopLevel' => {
message => q{Whether or not the keyword is one of the keywords for the page that was called. For the Wiki Front Page, it will only include top level keywords. For a keyword page, it would be true for any sub-keywords of this page.},
lastUpdated => 0,
context => q{template variable help},
},
};
1;

View file

@ -333,30 +333,6 @@ our $I18N =
context => 'Label for asset property',
},
'isKeywordPage' => {
message => q{A boolean that is true if this page is a keyword page.},
lastUpdated => 0,
context => 'template variable help',
},
'keyword_page_loop' => {
message => q{If this page is a keyword page, then this loop will contain a list of all pages tagged with this page's keyword. The pagination variables will apply to the list of pages in this loop. If this page is not a keyword page, the loop will be blank, and the pagination variables will not be present.},
lastUpdated => 0,
context => 'template variable help',
},
'keyword page title' => {
message => q{The title of a page that has this keyword.},
lastUpdated => 0,
context => 'template variable help',
},
'keyword page url' => {
message => q{The URL to a page that has this keyword. The URL will have the gateway URL prepended to it.},
lastUpdated => 0,
context => 'template variable help',
},
};
1;

View file

@ -77,7 +77,7 @@ our $I18N = {
},
'payment methods' => {
message => q|Payment Methods.|,
message => q|Payment Methods|,
lastUpdated => 1213313375,
context => q|Help body for the email receipt template|,
},
@ -93,6 +93,31 @@ our $I18N = {
lastUpdated => 0,
context => q{Link to begin checkout again after failure},
},
'template gone' => {
message => q|The template for entering in credentials has been deleted. Please notify the site administrator.|,
lastUpdated => 0,
context => q|Error message when a template cannot be accessed.|
},
'cart summary variables' => {
message => q|Cart Summary Variables|,
lastUpdated => 0,
context => q|Title for a template variable help page.|
},
'cart summary variables help' => {
message => q|These variables should be available in all PayDriver templates, to display the cart summary to the user.|,
lastUpdated => 0,
context => q|Body for a template variable help page.|
},
'proceedButton' => {
message => q|A combined button and form for the user to press when they have reviewed the charges that will be submitted to this payment gateway.|,
lastUpdated => 0,
context => q|Status message|,
},
};
1;

View file

@ -7,124 +7,13 @@ our $I18N = {
lastUpdated => 0,
context => q|Default Cash payment gateway label|
},
'phone' => {
message => q|Telephone Number|,
lastUpdated => 0,
context => q|Form label in the checkout form of the iTransact module.|
},
'country' => {
message => q|Country|,
lastUpdated => 0,
context => q|Form label in the checkout form of the iTransact module.|
},
'firstName' => {
message => q|First name|,
lastUpdated => 0,
context => q|Form label in the checkout form of the iTransact module.|
},
'lastName' => {
message => q|Last name|,
lastUpdated => 0,
context => q|Form label in the checkout form of the iTransact module.|
},
'address' => {
message => q|Address|,
lastUpdated => 1101772170,
context => q|Form label in the checkout form of the iTransact module.|
},
'city' => {
message => q|City|,
lastUpdated => 1101772171,
context => q|Form label in the checkout form of the iTransact module.|
},
'state' => {
message => q|State|,
lastUpdated => 1101772173,
context => q|Form label in the checkout form of the iTransact module.|
},
'zipcode' => {
message => q|Zipcode|,
lastUpdated => 1101772174,
context => q|Form label in the checkout form of the iTransact module.|
},
'email' => {
message => q|Email|,
lastUpdated => 1101772176,
context => q|Form label in the checkout form of the iTransact module.|
},
'cardNumber' => {
message => q|Credit card number|,
lastUpdated => 1101772177,
context => q|Form label in the checkout form of the iTransact module.|
},
'expiration date' => {
message => q|Expiration date|,
lastUpdated => 1101772180,
context => q|Form label in the checkout form of the iTransact module.|
},
'cvv2' => {
message => q|Verification number (ie. CVV2)|,
lastUpdated => 1101772182,
context => q|Form label in the checkout form of the iTransact module.|
},
'vendorId' => {
message => q|Username (Vendor ID)|,
lastUpdated => 0,
context => q|Form label in the configuration form of the iTransact module.|
},
'use cvv2' => {
message => q|Use CVV2|,
lastUpdated => 0,
context => q|Form label in the configuration form of the iTransact module.|
},
'emailMessage' => {
message => q|Email message|,
lastUpdated => 0,
context => q|Form label in the configuration form of the iTransact module.|
},
'password' => {
message => q|Password|,
lastUpdated => 0,
context => q|Form label in the configuration form of the iTransact module.|
},
'module name' => {
message => q|Cash|,
lastUpdated => 0,
context => q|The displayed name of the payment module.|
},
'invalid firstName' => {
message => q|You have to enter a valid first name.|,
lastUpdated => 0,
context => q|An error indicating that an invalid first name has been entered.|
},
'invalid lastName' => {
message => q|You have to enter a valid last name.|,
lastUpdated => 0,
context => q|An error indicating that an invalid last name has been entered.|
},
'invalid address' => {
message => q|You have to enter a valid address.|,
lastUpdated => 0,
context => q|An error indicating that an invalid street has been entered.|
},
'invalid city' => {
message => q|You have to enter a valid city.|,
lastUpdated => 0,
context => q|An error indicating that an invalid city has been entered.|
},
'invalid zip' => {
message => q|You have to enter a valid zipcode.|,
lastUpdated => 0,
context => q|An error indicating that an invalid zipcode has been entered.|
},
'invalid email' => {
message => q|You have to enter a valid email address.|,
lastUpdated => 0,
context => q|An error indicating that an invalid email address has been entered.|
},
'no description' => {
message => q|No description|,
lastUpdated => 0,
@ -158,6 +47,41 @@ our $I18N = {
message => q|When set to 'yes', the transaction is completed when the user submits payment details. When set to 'no', the transaction is set to pending and must be manually set to complete. This may be useful if you wish to allow site visitors to select the Cash Payment method, but would like to wait for payment to clear before completing the transaction.|,
lastUpdated => 0,
},
'summary template' => {
message => q|Summary Template|,
lastUpdated => 0,
context => q|Form label in the configuration form of the Cash module.|
},
'summary template help' => {
message => q|Pick a template to display the screen where the user confirms the cart summary info and agrees to pay.|,
lastUpdated => 0,
context => q|Hover help for the summary template field in the configuration form of the Cash module.|
},
'password' => {
message => q|Password|,
lastUpdated => 0,
context => q|Form label in the configuration form of the iTransact module.|
},
'password help' => {
message => q|The password for your ITransact account.|,
lastUpdated => 0,
context => q|Hover help for the password field in the configuration form of the iTransact module.|
},
'Pay' => {
message => q|Pay|,
lastUpdated => 0,
context => q|Button label|
},
'cart summary template' => {
message => q|Cash Payment Method Cart Summary Template|,
lastUpdated => 0,
context => q||,
},
};
1;

View file

@ -95,6 +95,41 @@ our $I18N = {
message => q{Username from Paypal credentials},
lastUpdated => 1247254128,
},
'summary template' => {
message => q|Summary Template|,
lastUpdated => 0,
context => q|Form label in the configuration form of the Cash module.|
},
'summary template help' => {
message => q|Pick a template to display the screen where the user confirms the cart summary info and agrees to pay.|,
lastUpdated => 0,
context => q|Hover help for the summary template field in the configuration form of the Cash module.|
},
'password' => {
message => q|Password|,
lastUpdated => 0,
context => q|Form label in the configuration form of the iTransact module.|
},
'password help' => {
message => q|The password for your ITransact account.|,
lastUpdated => 0,
context => q|Hover help for the password field in the configuration form of the iTransact module.|
},
'Pay' => {
message => q|Pay|,
lastUpdated => 0,
context => q|Button label|
},
'cart summary template' => {
message => q|PayPal Express Checkout Cart Summary Template|,
lastUpdated => 0,
context => q||
},
};
1;

View file

@ -12,56 +12,6 @@ our $I18N = {
lastUpdated => 0,
context => q|The name of the ITransact plugin|,
},
'label' => {
message => q|Credit Card|,
lastUpdated => 0,
context => q|Default ITransact payment gateway label|
},
'phone' => {
message => q|Telephone Number|,
lastUpdated => 0,
context => q|Form label in the checkout form of the iTransact module.|
},
'country' => {
message => q|Country|,
lastUpdated => 0,
context => q|Form label in the checkout form of the iTransact module.|
},
'firstName' => {
message => q|First name|,
lastUpdated => 0,
context => q|Form label in the checkout form of the iTransact module.|
},
'lastName' => {
message => q|Last name|,
lastUpdated => 0,
context => q|Form label in the checkout form of the iTransact module.|
},
'address' => {
message => q|Address|,
lastUpdated => 1101772170,
context => q|Form label in the checkout form of the iTransact module.|
},
'city' => {
message => q|City|,
lastUpdated => 1101772171,
context => q|Form label in the checkout form of the iTransact module.|
},
'state' => {
message => q|State|,
lastUpdated => 1101772173,
context => q|Form label in the checkout form of the iTransact module.|
},
'zipcode' => {
message => q|Zipcode|,
lastUpdated => 1101772174,
context => q|Form label in the checkout form of the iTransact module.|
},
'email' => {
message => q|Email|,
lastUpdated => 1101772176,
context => q|Form label in the checkout form of the iTransact module.|
},
'cardNumber' => {
message => q|Credit card number|,
lastUpdated => 1101772177,
@ -124,7 +74,7 @@ our $I18N = {
},
'edit credentials template' => {
message => q|Edit Credentials Template|,
message => q|ITransact Edit Credentials Template|,
lastUpdated => 0,
context => q|Title of the help page.|
},
@ -152,18 +102,6 @@ our $I18N = {
context => q|Template variable help.|
},
'addressField help' => {
message => q|A single text field for the user to enter in their street address.|,
lastUpdated => 0,
context => q|Template variable help.|
},
'emailField help' => {
message => q|A single text field for the user to enter in their email address.|,
lastUpdated => 1231192368,
context => q|Template variable help.|
},
'cardNumberField help' => {
message => q|A single text field for the user to enter in their credit card number.|,
lastUpdated => 0,

View file

@ -80,6 +80,17 @@ our $I18N = {
context => q|Hover help of a setting in the ogone config screen.|,
},
'summary template' => {
message => q|Summary Template|,
lastUpdated => 0,
context => q|Form label in the configuration form of the Cash module.|
},
'summary template help' => {
message => q|Pick a template to display the screen where the user confirms the cart summary info and agrees to pay.|,
lastUpdated => 0,
context => q|Hover help for the summary template field in the configuration form of the Cash module.|
},
'pay' => {
message => q|Pay|,
lastUpdated => 0,
@ -129,6 +140,13 @@ our $I18N = {
lastUpdated => 0,
context => q|Text that describes the required Ogone settings.|,
},
'cart summary template' => {
message => q|Ogone Payment Gateway Summary Template.|,
lastUpdated => 0,
context => q|Status message|,
},
};
1;

View file

@ -204,6 +204,41 @@ Additionally, set the &quot;Return URL&quot; to:|,
lastUpdated => 1245364211,
context => q|An informational message that's shown in the configuration form of this plugin.|
},
'summary template' => {
message => q|Summary Template|,
lastUpdated => 0,
context => q|Form label in the configuration form|
},
'summary template help' => {
message => q|Pick a template to display the screen where the user confirms the cart summary info and agrees to pay.|,
lastUpdated => 0,
context => q|Hover help for the summary template field in the configuration form|
},
'password' => {
message => q|Password|,
lastUpdated => 0,
context => q|Form label in the configuration form of the iTransact module.|
},
'password help' => {
message => q|The password for your ITransact account.|,
lastUpdated => 0,
context => q|Hover help for the password field in the configuration form of the iTransact module.|
},
'Pay' => {
message => q|Pay|,
lastUpdated => 0,
context => q|Button label|
},
'cart summary template' => {
message => q|PayPal Std Payment Driver Plugin Cart Summary Template|,
lastUpdated => 0,
context => q||
},
};
1;

View file

@ -201,12 +201,6 @@ our $I18N = {
context => q|a help description|,
},
'checkoutButton help' => {
message => q|The button the user pushes to choose a payment method.|,
lastUpdated => 0,
context => q|a help description|,
},
'continueShoppingButton help' => {
message => q|Clicking this button will take the user back to the site.|,
lastUpdated => 0,
@ -219,18 +213,6 @@ our $I18N = {
context => q|a help description|,
},
'chooseShippingButton help' => {
message => q|Clicking this button will let the user pick a shipping address from the address book.|,
lastUpdated => 0,
context => q|a help description|,
},
'shipToButton help' => {
message => q|Does the same as the chooseShippingButton.|,
lastUpdated => 0,
context => q|a help description|,
},
'subtotalPrice help' => {
message => q|The price of all the items in the cart.|,
lastUpdated => 0,
@ -976,6 +958,12 @@ our $I18N = {
context => q|a button the user clicks on to set shipping information|
},
'Special shipping' => {
message => q|Special shipping|,
lastUpdated => 0,
context => q|a button the user clicks on to set shipping information on an item|
},
'shipping address' => {
message => q|Shipping Address|,
lastUpdated => 0,
@ -1743,6 +1731,48 @@ our $I18N = {
context => q|commerce setting help|
},
'Billing Address' => {
message => q|Billing Address|,
lastUpdated => 0,
context => q|template label for the cart|
},
'Shipping Address' => {
message => q|Shipping Address|,
lastUpdated => 0,
context => q|template label for the cart|
},
'use same shipping as billing' => {
message => q|Use the same shipping address as billing address.|,
lastUpdated => 0,
context => q|template label for the cart|
},
'Add new address' => {
message => q|Add new address|,
lastUpdated => 0,
context => q|form label for the cart. Allows user to build a new address.|
},
'Update this address' => {
message => q|Update this address|,
lastUpdated => 0,
context => q|form label for the cart. Allows user to build a new address.|
},
'Choose a payment method' => {
message => q|Choose a payment method|,
lastUpdated => 0,
context => q|form label for the cart. Allows user to choose a payment method. Bart Jol for Minister in 2012!|
},
'shippableItemsInCart' => {
message => q|A boolean which will be true if any item in the cart requires shipping.|,
lastUpdated => 0,
context => q|form label for the cart. Allows user to choose a payment method. Bart Jol for Minister in 2012!|
},
};
1;

View file

@ -4304,7 +4304,7 @@ LongTruncOk=1</p>
},
'Contact Us' => {
message => q{All Contact Us},
message => q{Contact Us},
lastUpdated => 0,
context => q{Template label for automatically created Page layouts during Site Setup.},
},
@ -4316,7 +4316,7 @@ LongTruncOk=1</p>
},
'Forums' => {
message => q{Initial Pages},
message => q{Forums},
lastUpdated => 0,
context => q{Label for the Site Setup screen},
},