merge to 10219
This commit is contained in:
parent
ae28bf79c8
commit
4c1307e3d0
194 changed files with 8203 additions and 2134 deletions
|
|
@ -51,7 +51,7 @@ sub appendCommonVars {
|
|||
my $self = shift;
|
||||
my $var = shift;
|
||||
my $session = $self->session;
|
||||
my $user = $session->user;
|
||||
my $user = $self->getUser;
|
||||
|
||||
$var->{'user_full_name' } = $user->getWholeName;
|
||||
$var->{'user_member_since'} = $user->dateCreated;
|
||||
|
|
@ -242,7 +242,9 @@ sub editSettingsFormSave {
|
|||
|
||||
=head2 getLayoutTemplateId ( )
|
||||
|
||||
Override this method to return the template Id for the account layout.
|
||||
Override this method to return the template Id for the account layout. The default
|
||||
account layout draws a tabbed interface to the different account plugins, and displays
|
||||
the content from a particular screen from the account plugin.
|
||||
|
||||
=cut
|
||||
|
||||
|
|
@ -253,9 +255,10 @@ sub getLayoutTemplateId {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getStyleTemplate ( )
|
||||
=head2 getStyleTemplateId ( )
|
||||
|
||||
Override this method to return the template for the main style.
|
||||
Override this method to return the template for the main style. The style would
|
||||
be for the page that the account layout template is embedded in.
|
||||
|
||||
=cut
|
||||
|
||||
|
|
@ -278,8 +281,8 @@ the current module and do values will be used.
|
|||
|
||||
=head3 appendUID
|
||||
|
||||
If this flag is set and uid is passed along the url, the uid passed in will be
|
||||
appended to the end of it to the end of the url
|
||||
If this flag is set and uid is passed as a URL param, that uid will be
|
||||
appended to the end of the url.
|
||||
|
||||
=cut
|
||||
|
||||
|
|
@ -289,8 +292,8 @@ sub getUrl {
|
|||
my $appendUID = shift;
|
||||
|
||||
my $session = $self->session;
|
||||
my $form = $session->form;
|
||||
|
||||
my $uid = $self->uid;
|
||||
if($pairs) {
|
||||
#Append op=account to the url if it doesn't already exist
|
||||
unless ($pairs =~ m/op=account/){
|
||||
|
|
@ -301,7 +304,6 @@ sub getUrl {
|
|||
$pairs = q{op=account;module=}.$self->module.q{;do=}.$self->method;
|
||||
}
|
||||
|
||||
my $uid = $self->uid;
|
||||
$pairs .= ";uid=".$uid if($appendUID && $uid);
|
||||
|
||||
return $session->url->page($pairs);
|
||||
|
|
@ -309,6 +311,25 @@ sub getUrl {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getUser
|
||||
|
||||
Gets the user, either specified by the uid URL parameter, or the
|
||||
session user.
|
||||
|
||||
=cut
|
||||
|
||||
sub getUser {
|
||||
my $self = shift;
|
||||
if ($self->uid) {
|
||||
return WebGUI::User->new($self->session, $self->uid);
|
||||
}
|
||||
else {
|
||||
return $self->session->user;
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 new ( session, module [,method ,uid] )
|
||||
|
||||
Constructor.
|
||||
|
|
|
|||
|
|
@ -226,12 +226,6 @@ sub www_view {
|
|||
$self->appendCommonVars($var);
|
||||
$p->appendTemplateVars($var);
|
||||
|
||||
#Overwrite these
|
||||
my $user = WebGUI::User->new($session,$userId);
|
||||
$var->{'user_full_name' } = $user->getWholeName;
|
||||
$var->{'user_member_since' } = $user->dateCreated;
|
||||
|
||||
|
||||
return $self->processTemplate($var,$self->getViewTemplateId);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ sub getLayoutTemplateId {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getConfirmTemplateId ( )
|
||||
=head2 getRemoveConfirmTemplateId ( )
|
||||
|
||||
This method returns the template ID for the confirmation screen.
|
||||
|
||||
|
|
@ -484,17 +484,13 @@ sub www_view {
|
|||
my $var = {};
|
||||
|
||||
my $uid = $self->uid;
|
||||
my $user = ($uid) ? WebGUI::User->new($session,$uid) : $session->user;
|
||||
my $user = $self->getUser;
|
||||
|
||||
$self->appendCommonVars($var);
|
||||
|
||||
my $displayView = $uid ne "";
|
||||
$var->{'display_message'} = $msg;
|
||||
|
||||
#Override these
|
||||
$var->{'user_full_name' } = $user->getWholeName;
|
||||
$var->{'user_member_since' } = $user->dateCreated;
|
||||
|
||||
unless ($user->profileField('ableToBeFriend') && $user->profileIsViewable($session->user)) {
|
||||
my $i18n = WebGUI::International->new($session,"Account_Friends");
|
||||
my $errorMsg = "";
|
||||
|
|
|
|||
|
|
@ -107,13 +107,13 @@ sub appendCommonVars {
|
|||
my $self = shift;
|
||||
my $var = shift;
|
||||
my $session = $self->session;
|
||||
my $user = $session->user;
|
||||
my $user = $self->getUser;
|
||||
my $pageUrl = $session->url->page;
|
||||
|
||||
$self->SUPER::appendCommonVars($var);
|
||||
|
||||
$var->{'edit_profile_url' } = $self->getUrl("module=profile;do=edit");
|
||||
$var->{'invitations_enabled' } = $session->user->profileField('ableToBeFriend');
|
||||
$var->{'invitations_enabled' } = $user->profileField('ableToBeFriend');
|
||||
$var->{'profile_category_loop'} = [];
|
||||
|
||||
#Append the categories
|
||||
|
|
@ -475,10 +475,6 @@ sub www_view {
|
|||
|
||||
$self->appendCommonVars($var);
|
||||
|
||||
#Overwrite these
|
||||
$var->{'user_full_name' } = $user->getWholeName;
|
||||
$var->{'user_member_since' } = $user->dateCreated;
|
||||
$var->{'profile_user_id' } = $user->userId;
|
||||
$var->{'can_edit_profile' } = $uid eq $session->user->userId;
|
||||
|
||||
#Check user privileges
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ These methods are available from this class:
|
|||
|
||||
=head2 canView ( )
|
||||
|
||||
Returns whether or not the user can view the the tab for this module
|
||||
Returns whether or not the user can view the the tab for this module
|
||||
|
||||
=cut
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ sub canView {
|
|||
|
||||
=head2 editSettingsForm ( )
|
||||
|
||||
Creates form elements for user settings page custom to this account module
|
||||
Creates form elements for user settings page custom to this account module
|
||||
|
||||
=cut
|
||||
|
||||
|
|
@ -83,7 +83,7 @@ sub editSettingsForm {
|
|||
|
||||
=head2 editSettingsFormSave ( )
|
||||
|
||||
Creates form elements for the settings page custom to this account module
|
||||
Save form elements from the settings.
|
||||
|
||||
=cut
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ use strict;
|
|||
use WebGUI::AdSpace;
|
||||
use WebGUI::Macro;
|
||||
use WebGUI::Storage;
|
||||
use WebGUI::AssetCollateral::Sku::Ad::Ad;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
|
@ -81,6 +82,12 @@ Deletes this ad.
|
|||
|
||||
sub delete {
|
||||
my $self = shift;
|
||||
my $iterator = WebGUI::AssetCollateral::Sku::Ad::Ad->getAllIterator($self->session,{
|
||||
constraints => [ { "adSkuPurchase.adId = ?" => $self->getId } ],
|
||||
});
|
||||
while( my $object = $iterator->() ) {
|
||||
$object->update({'isDeleted' => 1});
|
||||
}
|
||||
my $storage = WebGUI::Storage->get($self->session, $self->get("storageId"));
|
||||
$storage->delete if defined $storage;
|
||||
$self->session->db->deleteRow("advertisement","adId",$self->getId);
|
||||
|
|
|
|||
|
|
@ -930,7 +930,7 @@ sub getEditForm {
|
|||
label => $i18n->get('keywords'),
|
||||
hoverHelp => $i18n->get('keywords help'),
|
||||
value => $self->get('keywords'),
|
||||
fieldType => 'text',
|
||||
fieldType => 'keywords',
|
||||
tab => 'meta',
|
||||
}
|
||||
);
|
||||
|
|
@ -2340,9 +2340,9 @@ sub update {
|
|||
# next unless (exists $properties->{$property} || exists $definition->{properties}{$property}{defaultValue});
|
||||
# skip a property unless it was specified to be set by the properties field
|
||||
next unless (exists $properties->{$property});
|
||||
|
||||
my $propertyDefinition = $definition->{properties}{$property};
|
||||
# skip a property if it has the display only flag set
|
||||
next if ($definition->{properties}{$property}{displayOnly});
|
||||
next if ($propertyDefinition->{displayOnly});
|
||||
|
||||
# skip properties that aren't yet in the table
|
||||
if (!exists $tableFields{$property}) {
|
||||
|
|
@ -2358,14 +2358,16 @@ sub update {
|
|||
}
|
||||
|
||||
# apply filter logic on a property to validate or fix it's value
|
||||
if (exists $definition->{properties}{$property}{filter}) {
|
||||
my $filter = $definition->{properties}{$property}{filter};
|
||||
$value = $self->$filter($value, $property);
|
||||
}
|
||||
if (exists $propertyDefinition->{filter}) {
|
||||
my $filter = $propertyDefinition->{filter};
|
||||
$value = $self->$filter($value, $property);
|
||||
}
|
||||
|
||||
# use the default value because default and update were both undef
|
||||
if ($value eq "" && exists $definition->{properties}{$property}{defaultValue}) {
|
||||
$value = $definition->{properties}{$property}{defaultValue};
|
||||
# if the value is undefined, use the default if possible
|
||||
# unless allowEmpty has been set, do this for empty strings as well
|
||||
if ( ( !defined $value || ( $value eq q{} && ! $propertyDefinition->{allowEmpty} ) )
|
||||
&& exists $propertyDefinition->{defaultValue} ) {
|
||||
$value = $propertyDefinition->{defaultValue};
|
||||
if (ref($value) eq 'ARRAY') {
|
||||
$value = $value->[0];
|
||||
}
|
||||
|
|
@ -2606,6 +2608,11 @@ NOTE: Don't try to override or overload this method. It won't work. What you are
|
|||
|
||||
sub www_editSave {
|
||||
my $self = shift;
|
||||
|
||||
my $annotations = "";
|
||||
if ($self->isa("WebGUI::Asset::File::Image")) {
|
||||
$annotations = $self->get("annotations");
|
||||
}
|
||||
##If this is a new asset (www_add), the parent may be locked. We should still be able to add a new asset.
|
||||
my $isNewAsset = $self->session->form->process("assetId") eq "new" ? 1 : 0;
|
||||
return $self->session->privilege->locked() if (!$self->canEditIfLocked and !$isNewAsset);
|
||||
|
|
@ -2644,6 +2651,12 @@ sub www_editSave {
|
|||
}
|
||||
}
|
||||
|
||||
if ($self->isa("WebGUI::Asset::File::Image")) {
|
||||
$object->update({ annotations => $annotations });
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
$object->updateHistory("edited");
|
||||
|
||||
# we handle auto commit assets here in case they didn't handle it themselves
|
||||
|
|
|
|||
|
|
@ -245,7 +245,6 @@ sub getEditFormUploadControl {
|
|||
return $html;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub getFileUrl {
|
||||
my $self = shift;
|
||||
|
|
@ -559,10 +558,11 @@ sub www_edit {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
||||
sub www_view {
|
||||
my $self = shift;
|
||||
return $self->session->privilege->noAccess() unless $self->canView;
|
||||
|
||||
|
||||
# Check to make sure it's not in the trash or some other weird place
|
||||
if ($self->get("state") ne "published") {
|
||||
my $i18n = WebGUI::International->new($self->session,'Asset_File');
|
||||
|
|
|
|||
|
|
@ -112,6 +112,10 @@ sub definition {
|
|||
fieldType => 'textarea',
|
||||
defaultValue => 'style="border-style:none;"',
|
||||
},
|
||||
annotations => {
|
||||
fieldType => 'textarea',
|
||||
defaultValue => '',
|
||||
},
|
||||
},
|
||||
};
|
||||
return $class->SUPER::definition($session,$definition);
|
||||
|
|
@ -236,17 +240,32 @@ sub view {
|
|||
return $out if $out;
|
||||
}
|
||||
my %var = %{$self->get};
|
||||
my ($crop_js, $domMe) = $self->annotate_js({ just_image => 1 });
|
||||
|
||||
if ($crop_js) {
|
||||
my ($style, $url) = $self->session->quick(qw(style url));
|
||||
|
||||
$style->setLink($url->extras('yui/build/fonts/fonts-min.css'), {rel=>'stylesheet', type=>'text/css'});
|
||||
$style->setLink($url->extras('yui/container/assets/container.css'), {rel=>'stylesheet', type=>'text/css'});
|
||||
$style->setScript($url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/container/container-min.js'), {type=>'text/javascript'});
|
||||
}
|
||||
|
||||
$var{controls} = $self->getToolbar;
|
||||
$var{fileUrl} = $self->getFileUrl;
|
||||
$var{fileIcon} = $self->getFileIconUrl;
|
||||
$var{thumbnail} = $self->getThumbnailUrl;
|
||||
my $out = $self->processTemplate(\%var,undef,$self->{_viewTemplate});
|
||||
$var{annotateJs} = "$crop_js$domMe";
|
||||
$var{parameters} = sprintf("id=%s", $self->getId());
|
||||
my $form = $self->session->form;
|
||||
my $out = $self->processTemplate(\%var,undef,$self->{_viewTemplate});
|
||||
if (!$self->session->var->isAdminOn && $self->get("cacheTimeout") > 10) {
|
||||
WebGUI::Cache->new($self->session,"view_".$self->getId)->set($out,$self->get("cacheTimeout"));
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 setFile ( filename )
|
||||
|
|
@ -268,6 +287,10 @@ sub www_edit {
|
|||
return $self->session->privilege->locked() unless $self->canEditIfLocked;
|
||||
my $i18n = WebGUI::International->new($self->session, 'Asset_Image');
|
||||
$self->getAdminConsole->addSubmenuItem($self->getUrl('func=resize'),$i18n->get("resize image")) if ($self->get("filename"));
|
||||
$self->getAdminConsole->addSubmenuItem($self->getUrl('func=rotate'),$i18n->get("rotate image")) if ($self->get("filename"));
|
||||
$self->getAdminConsole->addSubmenuItem($self->getUrl('func=crop'),$i18n->get("crop image")) if ($self->get("filename"));
|
||||
$self->getAdminConsole->addSubmenuItem($self->getUrl('func=annotate'),$i18n->get("annotate image")) if ($self->get("filename"));
|
||||
$self->getAdminConsole->addSubmenuItem($self->getUrl('func=undo'),$i18n->get("undo image")) if ($self->get("filename"));
|
||||
my $tabform = $self->getEditForm;
|
||||
$tabform->getTab("display")->template(
|
||||
-value=>$self->get("templateId"),
|
||||
|
|
@ -278,6 +301,283 @@ sub www_edit {
|
|||
return $self->getAdminConsole->render($tabform->print,$i18n->get("edit image"));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_undo {
|
||||
my $self = shift;
|
||||
my $previous = (@{$self->getRevisions()})[1];
|
||||
# instantiate assetId
|
||||
if ($previous) {
|
||||
# my $session = $self->session;
|
||||
|
||||
# my $cache = WebGUI::Cache->new($self->session, ["asset",$self->getId,$self->getRevisionDate]);
|
||||
# $cache->flush;
|
||||
# my $cache = WebGUI::Cache->new($previous->session, ["asset",$previous->getId,$previous->getRevisionDate]);
|
||||
# $cache->flush;
|
||||
|
||||
$self = $self->purgeRevision();
|
||||
# $self = undef;
|
||||
# $self = WebGUI::Asset->new($previous->session, $previous->getId, ref $previous, $previous->getRevisionDate);
|
||||
$self = $previous;
|
||||
$self->generateThumbnail;
|
||||
}
|
||||
return $self->www_edit();
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
#
|
||||
# All of the images will have to change to support annotate.
|
||||
# The revision system doesn't support the blobs, it seems.
|
||||
# All of the image operations will have to be updated to support annotations.
|
||||
#
|
||||
|
||||
sub www_annotate {
|
||||
my $self = shift;
|
||||
return $self->session->privilege->insufficient() unless $self->canEdit;
|
||||
return $self->session->privilege->locked() unless $self->canEditIfLocked;
|
||||
if (1) {
|
||||
my $newSelf = $self->addRevision();
|
||||
delete $newSelf->{_storageLocation};
|
||||
$newSelf->getStorageLocation->annotate($newSelf->get("filename"),$newSelf,$newSelf->session->form);
|
||||
$newSelf->setSize($newSelf->getStorageLocation->getFileSize($newSelf->get("filename")));
|
||||
$self = $newSelf;
|
||||
$self->generateThumbnail;
|
||||
}
|
||||
|
||||
my ($style, $url) = $self->session->quick(qw(style url));
|
||||
# $style->setLink($url->extras('annotate/imageMap.css'), {rel=>'stylesheet', type=>'text/css'});
|
||||
|
||||
$style->setLink($url->extras('yui/build/resize/assets/skins/sam/resize.css'), {rel=>'stylesheet', type=>'text/css'});
|
||||
$style->setLink($url->extras('yui/build/fonts/fonts-min.css'), {rel=>'stylesheet', type=>'text/css'});
|
||||
$style->setLink($url->extras('yui/build/imagecropper/assets/skins/sam/imagecropper.css'), {rel=>'stylesheet', type=>'text/css'});
|
||||
|
||||
$style->setScript($url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/element/element-beta-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/dragdrop/dragdrop-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/resize/resize-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/imagecropper/imagecropper-beta-min.js'), {type=>'text/javascript'});
|
||||
|
||||
# my $imageAsset = $self->session->db->getRow("ImageAsset","assetId",$self->getId);
|
||||
|
||||
my @pieces = split(/\n/, $self->get('annotations'));
|
||||
# my ($top_left, $width_height, $note) = split(/\n/, $imageAsset->{annotations});
|
||||
|
||||
my ($img_null, $tooltip_block, $tooltip_none) = ('', '', '');
|
||||
for (my $i = 0; $i < $#pieces; $i += 3) {
|
||||
$img_null .= "YAHOO.img.container.tt$i = null;\n";
|
||||
$tooltip_block .= "YAHOO.util.Dom.setStyle('tooltip$i', 'display', 'block');\n";
|
||||
$tooltip_none .= "YAHOO.util.Dom.setStyle('tooltip$i', 'display', 'none');\n";
|
||||
my $j = $i + 2;
|
||||
# warn("i: $i: ", $self->session->form->process("delAnnotate$i"));
|
||||
}
|
||||
|
||||
my $image = '<div align="center" class="yui-skin-sam"><img src="'.$self->getStorageLocation->getUrl($self->get("filename")).'" style="border-style:none;" alt="'.$self->get("filename").'" id="yui_img" /></div>';
|
||||
|
||||
my ($width, $height) = $self->getStorageLocation->getSize($self->get("filename"));
|
||||
|
||||
my @checkboxes = ();
|
||||
my $i18n = WebGUI::International->new($self->session,"Asset_Image");
|
||||
my $f = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl);
|
||||
|
||||
$self->getAdminConsole->addSubmenuItem($self->getUrl('func=edit'),$i18n->get("edit image"));
|
||||
$f->hidden(
|
||||
-name=>"func",
|
||||
-value=>"annotate"
|
||||
);
|
||||
$f->text(
|
||||
-label=>$i18n->get('annotate image'),
|
||||
-value=>'',
|
||||
-hoverHelp=>$i18n->get('annotate image description'),
|
||||
-name=>'annotate_text'
|
||||
);
|
||||
$f->integer(
|
||||
-label=>$i18n->get('top'),
|
||||
-name=>"annotate_top",
|
||||
-value=>,
|
||||
);
|
||||
$f->integer(
|
||||
-label=>$i18n->get('left'),
|
||||
-name=>"annotate_left",
|
||||
-value=>,
|
||||
);
|
||||
$f->integer(
|
||||
-label=>$i18n->get('width'),
|
||||
-name=>"annotate_width",
|
||||
-value=>,
|
||||
);
|
||||
$f->integer(
|
||||
-label=>$i18n->get('height'),
|
||||
-name=>"annotate_height",
|
||||
-value=>,
|
||||
);
|
||||
$f->button(
|
||||
-value=>$i18n->get('annotate'),
|
||||
-extras=>'onclick="switchState();"',
|
||||
);
|
||||
$f->submit;
|
||||
my ($crop_js, $domMe) = $self->annotate_js();
|
||||
return $self->getAdminConsole->render($f->print."$image$crop_js$domMe",$i18n->get("annotate image"));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub annotate_js {
|
||||
my $self = shift;
|
||||
my $opts = shift;
|
||||
|
||||
my @pieces = split(/\n/, $self->get('annotations'));
|
||||
|
||||
# warn("pieces: $#pieces: ". $self->getId());
|
||||
return "" if !@pieces && $opts->{just_image};
|
||||
|
||||
my ($img_null, $tooltip_block, $tooltip_none) = ('', '', '');
|
||||
for (my $i = 0; $i < $#pieces; $i += 3) {
|
||||
$img_null .= "YAHOO.img.container.tt$i = null;\n";
|
||||
$tooltip_block .= "YAHOO.util.Dom.setStyle('tooltip$i', 'display', 'block');\n";
|
||||
$tooltip_none .= "YAHOO.util.Dom.setStyle('tooltip$i', 'display', 'none');\n";
|
||||
my $j = $i + 2;
|
||||
# warn("i: $i: ", $self->session->form->process("delAnnotate$i"));
|
||||
}
|
||||
|
||||
my $id = $$opts{just_image} ? $self->getId : "yui_img";
|
||||
|
||||
my $crop_js = qq(
|
||||
<script type="text/javascript">
|
||||
var crop;
|
||||
function switchState() {
|
||||
$img_null
|
||||
|
||||
if (crop) {
|
||||
crop.destroy();
|
||||
crop = null;
|
||||
$tooltip_block
|
||||
}
|
||||
else {
|
||||
crop = new YAHOO.widget.ImageCropper('$id', {
|
||||
initialXY: [20, 20],
|
||||
keyTick: 5,
|
||||
shiftKeyTick: 50
|
||||
});
|
||||
crop.on('moveEvent', function() {
|
||||
var region = crop.getCropCoords();
|
||||
element = document.getElementById('annotate_width_formId');
|
||||
element.value = region.width;
|
||||
element = document.getElementById('annotate_height_formId');
|
||||
element.value = region.height;
|
||||
element = document.getElementById('annotate_top_formId');
|
||||
element.value = region.top;
|
||||
element = document.getElementById('annotate_left_formId');
|
||||
element.value = region.left;
|
||||
});
|
||||
$tooltip_none
|
||||
}
|
||||
}
|
||||
</script>
|
||||
);
|
||||
|
||||
my $hotspots = '';
|
||||
my $domMe = '';
|
||||
|
||||
for (my $i = 0; $i < $#pieces; $i += 3) {
|
||||
my $top_left = $pieces[$i];
|
||||
my $width_height = $pieces[$i + 1];
|
||||
my $note = $pieces[$i + 2];
|
||||
|
||||
if ($top_left =~ /top: (\d+)px; left: (\d+)px;/) {
|
||||
$top_left = "xy[0]+$1, xy[1]+$2";
|
||||
}
|
||||
|
||||
my ($width, $height) = ("", "");
|
||||
if ($width_height =~ /width: (\d+)px; height: (\d+)px;/) {
|
||||
($width, $height) = ("$1px", "$2px");
|
||||
}
|
||||
|
||||
# next if 3 == $i;
|
||||
|
||||
warn('next');
|
||||
$domMe .= qq(
|
||||
<style type="text/css">
|
||||
div#tooltip$i { position: absolute; border:1px solid; }
|
||||
</style>
|
||||
|
||||
<span id=span_tooltip$i>
|
||||
</span>
|
||||
|
||||
<script type="text/javascript">
|
||||
function on_load_$i() {
|
||||
var xy = YAHOO.util.Dom.getXY('$id');
|
||||
|
||||
document.getElementById('span_tooltip$i').innerHTML = "<div id=tooltip$i style='border:1px solid;'></div>";
|
||||
YAHOO.util.Dom.setStyle('tooltip$i', 'display', 'block');
|
||||
YAHOO.util.Dom.setStyle('tooltip$i', 'height', '$height');
|
||||
YAHOO.util.Dom.setStyle('tooltip$i', 'width', '$width');
|
||||
YAHOO.util.Dom.setXY('span_tooltip$i', [$top_left]);
|
||||
YAHOO.util.Dom.setXY('tooltip$i', [$top_left]);
|
||||
|
||||
YAHOO.namespace("img.container");
|
||||
YAHOO.img.container.tt$i = new YAHOO.widget.Tooltip("tt$i", { showdelay: 0, visible: true, context:"tooltip$i", position:"relative", container:"tooltip$i", text:"$note" });
|
||||
}
|
||||
if (document.addEventListener) {
|
||||
document.addEventListener("DOMContentLoaded", on_load_$i, false);
|
||||
}
|
||||
else if (window.attachEvent){
|
||||
window.attachEvent('onload', on_load_$i);
|
||||
}
|
||||
|
||||
</script>
|
||||
);
|
||||
}
|
||||
|
||||
return($crop_js, $domMe);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_rotate {
|
||||
my $self = shift;
|
||||
return $self->session->privilege->insufficient() unless $self->canEdit;
|
||||
return $self->session->privilege->locked() unless $self->canEditIfLocked;
|
||||
# warn(sprintf("Rotate_formId: %s", $self->session->form->process("Rotate")));
|
||||
if (defined $self->session->form->process("Rotate")) {
|
||||
my $newSelf = $self->addRevision();
|
||||
delete $newSelf->{_storageLocation};
|
||||
$newSelf->getStorageLocation->rotate($newSelf->get("filename"),$newSelf->session->form->process("Rotate"));
|
||||
$newSelf->setSize($newSelf->getStorageLocation->getFileSize($newSelf->get("filename")));
|
||||
$self = $newSelf;
|
||||
$self->generateThumbnail;
|
||||
}
|
||||
|
||||
my ($x, $y) = $self->getStorageLocation->getSizeInPixels($self->get("filename"));
|
||||
|
||||
##YUI specific datatable CSS
|
||||
my ($style, $url) = $self->session->quick(qw(style url));
|
||||
|
||||
my $img_name = $self->getStorageLocation->getUrl($self->get("filename"));
|
||||
my $img_file = $self->get("filename");
|
||||
my $image = '<div align="center" class="yui-skin-sam"><img src="'.$self->getStorageLocation->getUrl($self->get("filename")).'" style="border-style:none;" alt="'.$self->get("filename").'" id="yui_img" /></div>';
|
||||
|
||||
my $i18n = WebGUI::International->new($self->session,"Asset_Image");
|
||||
$self->getAdminConsole->addSubmenuItem($self->getUrl('func=edit'),$i18n->get("edit image"));
|
||||
my $f = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl);
|
||||
$f->hidden(
|
||||
-name=>"func",
|
||||
-value=>"rotate"
|
||||
);
|
||||
$f->button(
|
||||
-value=>"Left",
|
||||
-extras=>qq(onclick="var deg = document.getElementById('Rotate_formId').value; deg = parseInt(deg) + 90; document.getElementById('Rotate_formId').value = deg;"),
|
||||
);
|
||||
$f->button(
|
||||
-value=>"Right",
|
||||
-extras=>qq(onclick="var deg = document.getElementById('Rotate_formId').value; deg = parseInt(deg) - 90; document.getElementById('Rotate_formId').value = deg;"),
|
||||
);
|
||||
$f->integer(
|
||||
-label=>$i18n->get('degree'),
|
||||
-name=>"Rotate",
|
||||
-value=>0,
|
||||
);
|
||||
$f->submit;
|
||||
return $self->getAdminConsole->render($f->print.$image,$i18n->get("rotate image"));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_resize {
|
||||
my $self = shift;
|
||||
|
|
@ -289,7 +589,59 @@ sub www_resize {
|
|||
$newSelf->getStorageLocation->resize($newSelf->get("filename"),$newSelf->session->form->process("newWidth"),$newSelf->session->form->process("newHeight"));
|
||||
$newSelf->setSize($newSelf->getStorageLocation->getFileSize($newSelf->get("filename")));
|
||||
$self = $newSelf;
|
||||
$self->generateThumbnail;
|
||||
}
|
||||
|
||||
my ($x, $y) = $self->getStorageLocation->getSizeInPixels($self->get("filename"));
|
||||
|
||||
##YUI specific datatable CSS
|
||||
my ($style, $url) = $self->session->quick(qw(style url));
|
||||
|
||||
$style->setLink($url->extras('yui/build/fonts/fonts-min.css'), {rel=>'stylesheet', type=>'text/css'});
|
||||
$style->setLink($url->extras('yui/build/resize/assets/skins/sam/resize.css'), {rel=>'stylesheet', type=>'text/css'});
|
||||
$style->setScript($url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/element/element-beta-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/dragdrop/dragdrop-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/resize/resize-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/animation/animation-min.js'), {type=>'text/javascript'});
|
||||
|
||||
my $resize_js = qq(
|
||||
<script>
|
||||
(function() {
|
||||
var Dom = YAHOO.util.Dom,
|
||||
Event = YAHOO.util.Event;
|
||||
|
||||
var resize = new YAHOO.util.Resize('yui_img', {
|
||||
handles: 'all',
|
||||
knobHandles: true,
|
||||
height: '${x}px',
|
||||
width: '${y}px',
|
||||
proxy: true,
|
||||
ghost: true,
|
||||
status: true,
|
||||
draggable: false,
|
||||
ratio: true,
|
||||
animate: true,
|
||||
animateDuration: .75,
|
||||
animateEasing: YAHOO.util.Easing.backBoth
|
||||
});
|
||||
|
||||
resize.on('startResize', function() {
|
||||
this.getProxyEl().innerHTML = '<img src="' + this.get('element').src + '" style="height: 100%; width: 100%;">';
|
||||
Dom.setStyle(this.getProxyEl().firstChild, 'opacity', '.25');
|
||||
}, resize, true);
|
||||
|
||||
resize.on('resize', function(e) {
|
||||
element = document.getElementById('newWidth_formId');
|
||||
element.value = e.width;
|
||||
|
||||
element = document.getElementById('newHeight_formId');
|
||||
element.value = e.height;
|
||||
}, resize, true);
|
||||
})();
|
||||
</script>
|
||||
);
|
||||
|
||||
my $i18n = WebGUI::International->new($self->session,"Asset_Image");
|
||||
$self->getAdminConsole->addSubmenuItem($self->getUrl('func=edit'),$i18n->get("edit image"));
|
||||
my $f = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl);
|
||||
|
|
@ -297,7 +649,6 @@ sub www_resize {
|
|||
-name=>"func",
|
||||
-value=>"resize"
|
||||
);
|
||||
my ($x, $y) = $self->getStorageLocation->getSizeInPixels($self->get("filename"));
|
||||
$f->readOnly(
|
||||
-label=>$i18n->get('image size'),
|
||||
-hoverHelp=>$i18n->get('image size description'),
|
||||
|
|
@ -316,15 +667,121 @@ sub www_resize {
|
|||
-value=>$y,
|
||||
);
|
||||
$f->submit;
|
||||
my $image = '<div align="center"><img src="'.$self->getStorageLocation->getUrl($self->get("filename")).'" style="border-style:none;" alt="'.$self->get("filename").'" /></div>';
|
||||
my $image = '<div align="center" class="yui-skin-sam"><img src="'.$self->getStorageLocation->getUrl($self->get("filename")).'" style="border-style:none;" alt="'.$self->get("filename").'" id="yui_img" /></div>'.$resize_js;
|
||||
return $self->getAdminConsole->render($f->print.$image,$i18n->get("resize image"));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_crop {
|
||||
my $self = shift;
|
||||
return $self->session->privilege->insufficient() unless $self->canEdit;
|
||||
return $self->session->privilege->locked() unless $self->canEditIfLocked;
|
||||
|
||||
if ($self->session->form->process("Width") || $self->session->form->process("Height")
|
||||
|| $self->session->form->process("Top") || $self->session->form->process("Left")) {
|
||||
my $newSelf = $self->addRevision();
|
||||
delete $newSelf->{_storageLocation};
|
||||
$newSelf->getStorageLocation->crop(
|
||||
$newSelf->get("filename"),
|
||||
$newSelf->session->form->process("Width"),
|
||||
$newSelf->session->form->process("Height"),
|
||||
$newSelf->session->form->process("Top"),
|
||||
$newSelf->session->form->process("Left")
|
||||
);
|
||||
$self = $newSelf;
|
||||
$self->generateThumbnail;
|
||||
}
|
||||
|
||||
my $filename = $self->get("filename");
|
||||
|
||||
##YUI specific datatable CSS
|
||||
my ($style, $url) = $self->session->quick(qw(style url));
|
||||
|
||||
my $crop_js = qq(
|
||||
<script>
|
||||
(function() {
|
||||
var Dom = YAHOO.util.Dom, Event = YAHOO.util.Event, results = null;
|
||||
|
||||
Event.onDOMReady(function() {
|
||||
var crop = new YAHOO.widget.ImageCropper('yui_img', {
|
||||
initialXY: [20, 20],
|
||||
keyTick: 5,
|
||||
shiftKeyTick: 50
|
||||
});
|
||||
crop.on('moveEvent', function() {
|
||||
var region = crop.getCropCoords();
|
||||
element = document.getElementById('Width_formId');
|
||||
element.value = region.width;
|
||||
element = document.getElementById('Height_formId');
|
||||
element.value = region.height;
|
||||
element = document.getElementById('Top_formId');
|
||||
element.value = region.top;
|
||||
element = document.getElementById('Left_formId');
|
||||
element.value = region.left;
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
);
|
||||
|
||||
$style->setLink($url->extras('yui/build/resize/assets/skins/sam/resize.css'), {rel=>'stylesheet', type=>'text/css'});
|
||||
$style->setLink($url->extras('yui/build/fonts/fonts-min.css'), {rel=>'stylesheet', type=>'text/css'});
|
||||
$style->setLink($url->extras('yui/build/imagecropper/assets/skins/sam/imagecropper.css'), {rel=>'stylesheet', type=>'text/css'});
|
||||
$style->setScript($url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/element/element-beta-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/dragdrop/dragdrop-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/resize/resize-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/imagecropper/imagecropper-beta-min.js'), {type=>'text/javascript'});
|
||||
|
||||
my $i18n = WebGUI::International->new($self->session,"Asset_Image");
|
||||
|
||||
$self->getAdminConsole->addSubmenuItem($self->getUrl('func=edit'),$i18n->get("edit image"));
|
||||
my $f = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl);
|
||||
$f->hidden(
|
||||
-name=>"degree",
|
||||
-value=>"0"
|
||||
);
|
||||
$f->hidden(
|
||||
-name=>"func",
|
||||
-value=>"crop"
|
||||
);
|
||||
my ($x, $y) = $self->getStorageLocation->getSizeInPixels($filename);
|
||||
$f->integer(
|
||||
-label=>$i18n->get('width'),
|
||||
-hoverHelp=>$i18n->get('new width description'),
|
||||
-name=>"Width",
|
||||
-value=>$x,
|
||||
);
|
||||
$f->integer(
|
||||
-label=>$i18n->get('height'),
|
||||
-hoverHelp=>$i18n->get('new height description'),
|
||||
-name=>"Height",
|
||||
-value=>$y,
|
||||
);
|
||||
$f->integer(
|
||||
-label=>$i18n->get('top'),
|
||||
-hoverHelp=>$i18n->get('new width description'),
|
||||
-name=>"Top",
|
||||
-value=>$x,
|
||||
);
|
||||
$f->integer(
|
||||
-label=>$i18n->get('left'),
|
||||
-hoverHelp=>$i18n->get('new height description'),
|
||||
-name=>"Left",
|
||||
-value=>$y,
|
||||
);
|
||||
$f->submit;
|
||||
|
||||
my $image = '<div align="center" class="yui-skin-sam"><img src="'.$self->getStorageLocation->getUrl($filename).'" style="border-style:none;" alt="'.$filename.'" id="yui_img" /></div>'.$crop_js;
|
||||
|
||||
return $self->getAdminConsole->render($f->print.$image,$i18n->get("crop image"));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# Use superclass method for now.
|
||||
sub www_view {
|
||||
my $self = shift;
|
||||
$self->SUPER::www_view;
|
||||
return($self->SUPER::www_view);
|
||||
}
|
||||
|
||||
#sub www_view {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,22 @@ These methods are available from this class:
|
|||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 unzip ( $storage, $filename )
|
||||
|
||||
Uncompress and/or expand an archive, based on the file extension of the filename.
|
||||
Returns 1 if the unzip was successful. Returns 0 if there were problems.
|
||||
|
||||
=head3 $storage
|
||||
|
||||
A WebGUI::Storage object containing the archive.
|
||||
|
||||
=head3 $filename
|
||||
|
||||
The filename of the archive.
|
||||
|
||||
=cut
|
||||
|
||||
sub unzip {
|
||||
my $self = shift;
|
||||
my $storage = shift;
|
||||
|
|
@ -78,8 +94,8 @@ sub unzip {
|
|||
|
||||
=head2 addRevision ( )
|
||||
|
||||
This method exists for demonstration purposes only. The superclass
|
||||
handles revisions to ZipArchive Assets.
|
||||
This method exists for demonstration purposes only. The superclass
|
||||
handles revisions to ZipArchive Assets.
|
||||
|
||||
=cut
|
||||
|
||||
|
|
|
|||
|
|
@ -304,6 +304,14 @@ sub getEditForm {
|
|||
-hoverHelp =>$i18n->get("description description"),
|
||||
-value =>$self->getValue('description'),
|
||||
);
|
||||
if ($self->getParent->canEdit) {
|
||||
$form->user(
|
||||
name =>"ownerUserId",
|
||||
value =>$self->getValue('ownerUserId'),
|
||||
label =>$i18n->get('maintainer label'),
|
||||
hoverHelp =>$i18n->get('maintainer description'),
|
||||
);
|
||||
}
|
||||
$form->text(
|
||||
-name =>'version',
|
||||
-defaultValue =>undef,
|
||||
|
|
@ -335,21 +343,17 @@ sub getEditForm {
|
|||
|
||||
foreach my $category (keys %{$self->getParent->getCategories}) {
|
||||
$form->raw('<tr><td colspan="2"><b>'.$category.'</b></td></tr>');
|
||||
my $attributes;
|
||||
if ($session->form->process('func') eq 'add'){
|
||||
$attributes = $db->read("select * from Matrix_attribute where category = ? and assetId = ?",
|
||||
[$category,$matrixId]);
|
||||
}
|
||||
else{
|
||||
$attributes = $db->read("select * from Matrix_attribute as attribute
|
||||
left join MatrixListing_attribute as listing using(attributeId)
|
||||
where listing.matrixListingId = ? and category =? and attribute.assetId = ?",
|
||||
[$self->getId,$category,$matrixId]);
|
||||
}
|
||||
my $attributes = $db->read("select * from Matrix_attribute where category = ? and assetId = ?",
|
||||
[$category,$matrixId]);
|
||||
while (my $attribute = $attributes->hashRef) {
|
||||
$attribute->{label} = $attribute->{name};
|
||||
$attribute->{subtext} = $attribute->{description};
|
||||
$attribute->{name} = 'attribute_'.$attribute->{attributeId};
|
||||
unless($session->form->process('func') eq 'add'){
|
||||
$attribute->{value} = $db->quickScalar("select value from MatrixListing_attribute
|
||||
where attributeId = ? and matrixId = ? and matrixListingId = ?",
|
||||
[$attribute->{attributeId},$matrixId,$self->getId]);
|
||||
}
|
||||
if($attribute->{fieldType} eq 'Combo'){
|
||||
my %options;
|
||||
tie %options, 'Tie::IxHash';
|
||||
|
|
@ -559,7 +563,7 @@ sub setRatings {
|
|||
|
||||
my $half = round($count/2);
|
||||
my $mean = $sum / ($count || 1);
|
||||
my $median = $db->quickScalar("select rating $sql limit $half,$half",[$self->getId,$category]);
|
||||
my $median = $db->quickScalar("select rating $sql order by rating limit $half,1",[$self->getId,$category]);
|
||||
|
||||
$db->write("replace into MatrixListing_ratingSummary
|
||||
(listingId, category, meanValue, medianValue, countValue, assetId)
|
||||
|
|
@ -570,7 +574,7 @@ sub setRatings {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 view ( hasRated )
|
||||
=head2 updateScore ( )
|
||||
|
||||
Updates the score of a MatrixListing.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,205 +0,0 @@
|
|||
package WebGUI::Asset::RSSCapable;
|
||||
|
||||
=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 NEXT;
|
||||
use WebGUI::Asset::RSSFromParent;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
WebGUI::Asset::RSSCapable
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
An extra mixin class to be included before WebGUI::Asset in any asset
|
||||
class that wishes its instances to be capable of generating RSS feeds
|
||||
using the RSSFromParent asset.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use base 'WebGUI::Asset::RSSCapable';
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my %properties;
|
||||
tie %properties, 'Tie::IxHash';
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_RSSCapable');
|
||||
|
||||
# We do this prefixing to avoid name collisions because properties aren't namespaced.
|
||||
%properties =
|
||||
(
|
||||
rssCapableRssEnabled => { tab => 'display',
|
||||
fieldType => 'yesNo',
|
||||
defaultValue => 1,
|
||||
label => $i18n->get('rssEnabled label'),
|
||||
hoverHelp => $i18n->get('rssEnabled hoverHelp')
|
||||
},
|
||||
rssCapableRssTemplateId => { tab => 'display',
|
||||
fieldType => 'template',
|
||||
defaultValue => 'PBtmpl0000000000000142',
|
||||
namespace => 'RSSCapable/RSS',
|
||||
label => $i18n->get('rssTemplateId label'),
|
||||
hoverHelp => $i18n->get('rssTemplateId hoverHelp')
|
||||
},
|
||||
rssCapableRssFromParentId => { fieldType => 'hidden',
|
||||
noFormPost => 1,
|
||||
defaultValue => undef,
|
||||
},
|
||||
);
|
||||
|
||||
push @$definition, { assetName => $i18n->get('assetName'),
|
||||
tableName => 'RSSCapable',
|
||||
autoGenerateForms => 1,
|
||||
className => 'WebGUI::Asset::RSSCapable',
|
||||
icon => 'rssCapable.gif',
|
||||
properties => \%properties
|
||||
};
|
||||
return $class->NEXT::definition($session, $definition);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub _rssFromParentValid {
|
||||
my $self = shift;
|
||||
my $rssFromParentId = $self->get('rssCapableRssFromParentId');
|
||||
return undef unless $rssFromParentId;
|
||||
|
||||
my $rssFromParent = WebGUI::Asset->newByDynamicClass($self->session, $rssFromParentId);
|
||||
return undef unless $rssFromParent;
|
||||
return ($rssFromParent->isa('WebGUI::Asset::RSSFromParent')
|
||||
&& $rssFromParent->getParent->getId eq $self->getId);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub _updateRssFromParentProperties {
|
||||
my $self = shift;
|
||||
my $rssFromParent = WebGUI::Asset->newByDynamicClass($self->session,
|
||||
$self->get('rssCapableRssFromParentId'));
|
||||
$rssFromParent->update({ title => $self->get('title'),
|
||||
menuTitle => $self->get('menuTitle') });
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub _purgeExtraRssFromParentAssets {
|
||||
my $self = shift;
|
||||
my $rssFromParentId = $self->get('rssCapableRssFromParentId');
|
||||
|
||||
foreach my $rssFromParent (@{$self->getLineage(['children'],
|
||||
{returnObjects => 1,
|
||||
includeOnlyClasses =>
|
||||
['WebGUI::Asset::RSSFromParent']})}) {
|
||||
$rssFromParent->purge unless $rssFromParent->getId eq $rssFromParentId;
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub _ensureRssFromParentPresent {
|
||||
my $self = shift;
|
||||
if (!$self->_rssFromParentValid) {
|
||||
# Create a new one.
|
||||
my $rssFromParent = $self->addChild({ className => 'WebGUI::Asset::RSSFromParent',
|
||||
title => $self->get('title'),
|
||||
menuTitle => $self->get('menuTitle'),
|
||||
url => $self->get('url').'.rss'
|
||||
});
|
||||
$self->update({ rssCapableRssFromParentId => $rssFromParent->getId });
|
||||
}
|
||||
|
||||
$self->_updateRssFromParentProperties;
|
||||
$self->_purgeExtraRssFromParentAssets;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub _ensureRssFromParentAbsent {
|
||||
my $self = shift;
|
||||
# Invalidate it, and then it'll get purged along with any others.
|
||||
$self->update({ rssCapableRssFromParentId => undef });
|
||||
$self->_purgeExtraRssFromParentAssets;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub processPropertiesFromFormPost {
|
||||
my $self = shift;
|
||||
my $error = $self->NEXT::processPropertiesFromFormPost(@_);
|
||||
return $error if ref $error eq 'ARRAY';
|
||||
if ($self->get('rssCapableRssEnabled')) {
|
||||
$self->_ensureRssFromParentPresent;
|
||||
} else {
|
||||
$self->_ensureRssFromParentAbsent;
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getRssUrl ( )
|
||||
|
||||
Returns the site-relative URL to the RSS feed for this asset, or undef
|
||||
if there is no such feed.
|
||||
|
||||
=cut
|
||||
|
||||
sub getRssUrl {
|
||||
my $self = shift;
|
||||
my $rssFromParentId = $self->get('rssCapableRssFromParentId');
|
||||
return undef unless $rssFromParentId;
|
||||
my $rssAsset = WebGUI::Asset->newByDynamicClass($self->session, $rssFromParentId);
|
||||
return undef unless $rssAsset;
|
||||
return $rssAsset->getUrl;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getRssItems ( )
|
||||
|
||||
Returns a list of RSS items for a feed corresponding to this asset.
|
||||
Each item may be another asset, or a hash of (properly XMLized)
|
||||
properties for the <item>..</item> tag. Defaults to no items.
|
||||
|
||||
This is the primary method that RSSCapable assets should override.
|
||||
|
||||
=cut
|
||||
|
||||
sub getRssItems { () }
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_viewRSS ( )
|
||||
|
||||
Default www method for methods that return RSS. This will redirect to the getRssUrl unless overridden.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_viewRSS {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
|
||||
my $rssUrl = $self->getRssUrl;
|
||||
|
||||
if($rssUrl) {
|
||||
$session->http->setRedirect($self->getRssUrl);
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
package WebGUI::Asset::RSSFromParent;
|
||||
|
||||
=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 HTML::Entities;
|
||||
use Tie::IxHash;
|
||||
use base 'WebGUI::Asset';
|
||||
use WebGUI::Utility;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Asset::RSSFromParent
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Generates an RSS feed from the children/descendants of its parent.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use WebGUI::Asset::RSSFromParent;
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my %properties;
|
||||
tie %properties, 'Tie::IxHash';
|
||||
my $i18n = WebGUI::International->new($session, "Asset_RSSFromParent");
|
||||
|
||||
%properties = ();
|
||||
|
||||
push(@{$definition}, {
|
||||
assetName=>$i18n->get('assetName'),
|
||||
icon=>'rssGear.gif',
|
||||
autoGenerateForms=>1,
|
||||
tableName=>'RSSFromParent',
|
||||
className=>'WebGUI::Asset::RSSFromParent',
|
||||
properties=>\%properties
|
||||
});
|
||||
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 update
|
||||
|
||||
=cut
|
||||
|
||||
sub update {
|
||||
# Re-force isHidden to 1 on each update; these should always be hidden.
|
||||
my $self = shift;
|
||||
my $properties = shift;
|
||||
$self->SUPER::update(+{%$properties, isHidden => 1});
|
||||
}
|
||||
|
||||
#------------------------------------------------
|
||||
|
||||
=head2 _escapeXml
|
||||
|
||||
=cut
|
||||
|
||||
sub _escapeXml {
|
||||
my $text = shift;
|
||||
return $text unless (ref $text eq "");
|
||||
return HTML::Entities::encode_numeric($text)
|
||||
}
|
||||
|
||||
#------------------------------------------------
|
||||
|
||||
=head2 _tlsOfAsset
|
||||
|
||||
=cut
|
||||
|
||||
sub _tlsOfAsset {
|
||||
my $self = shift;
|
||||
my $asset = shift;
|
||||
#Fix Title
|
||||
my $title = _escapeXml($asset->get('title'));
|
||||
#Fix Url
|
||||
my $url = _escapeXml($self->session->url->getSiteURL() . $asset->getUrl);
|
||||
#Fix Description
|
||||
my $description = _escapeXml($asset->get('synopsis'));
|
||||
return ($title,$url,$description);
|
||||
}
|
||||
|
||||
#------------------------------------------------
|
||||
|
||||
=head2 {
|
||||
|
||||
=cut
|
||||
|
||||
sub isValidRssItem { 0 }
|
||||
|
||||
#------------------------------------------------
|
||||
|
||||
=head2 displayInFolder2
|
||||
|
||||
=cut
|
||||
|
||||
sub displayInFolder2 { 0 }
|
||||
|
||||
#------------------------------------------------
|
||||
|
||||
=head2 www_view
|
||||
|
||||
=cut
|
||||
|
||||
sub www_view {
|
||||
my $self = shift;
|
||||
return '' unless $self->session->asset->getId eq $self->getId;
|
||||
return '' unless $self->getParent->isa('WebGUI::Asset::RSSCapable');
|
||||
return '' unless $self->getParent->canView; # Go to parent for auth
|
||||
my $parent = $self->getParent;
|
||||
my $template = WebGUI::Asset::Template->new($self->session, $parent->get('rssCapableRssTemplateId'));
|
||||
$template->prepare($self->getMetaDataAsTemplateVariables);
|
||||
$self->session->http->setMimeType('text/xml');
|
||||
|
||||
my $var = {};
|
||||
@$var{'title', 'link', 'description'} = $self->_tlsOfAsset($parent);
|
||||
$var->{'generator'} = "WebGUI $WebGUI::VERSION";
|
||||
$var->{'lastBuildDate'} = $self->session->datetime->epochToMail($parent->getContentLastModified);
|
||||
$var->{'webMaster'} = $self->session->setting->get('companyEmail');
|
||||
$var->{'docs'} = 'http://blogs.law.harvard.edu/tech/rss';
|
||||
|
||||
my @items = $parent->getRssItems;
|
||||
$var->{'item_loop'} = [];
|
||||
my $counter = 0;
|
||||
foreach my $item (@items) {
|
||||
my $subvar = {};
|
||||
|
||||
if (UNIVERSAL::isa($item, 'WebGUI::Asset')) {
|
||||
next unless $item->isValidRssItem;
|
||||
$subvar = {};
|
||||
@$subvar{'title', 'link', 'description'} = $self->_tlsOfAsset($item);
|
||||
$subvar->{guid} = $subvar->{link};
|
||||
$subvar->{pubDate} = _escapeXml($self->session->datetime->epochToMail($item->get('creationDate')));
|
||||
} elsif (ref $item eq 'HASH') {
|
||||
foreach my $key (keys %$item) {
|
||||
$subvar->{$key} = _escapeXml($item->{$key});
|
||||
}
|
||||
} else {
|
||||
$self->session->errorHandler->error("Don't know what to do with this RSS item: $item");
|
||||
next;
|
||||
}
|
||||
$counter++;
|
||||
push @{$var->{'item_loop'}}, $subvar;
|
||||
}
|
||||
|
||||
return $self->processTemplate($var, undef, $template);
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
@ -126,14 +126,6 @@ sub view {
|
|||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_edit {
|
||||
my $self = shift;
|
||||
return $self->session->privilege->insufficient() unless $self->canEdit;
|
||||
return $self->session->privilege->locked() unless $self->canEditIfLocked;
|
||||
return $self->getAdminConsole->render($self->getEditForm->print, $self->addEditLabel);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_view
|
||||
|
|
|
|||
|
|
@ -448,6 +448,18 @@ sub getToolbar {
|
|||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getRichEditor ( $nameId )
|
||||
|
||||
Return the javascript needed to make the Rich Editor.
|
||||
|
||||
=head3 $nameId
|
||||
|
||||
The id for the rich editor, should be unique enough to be used as the id parameter
|
||||
for a HTML tag.
|
||||
|
||||
=cut
|
||||
|
||||
sub getRichEditor {
|
||||
my $self = shift;
|
||||
return '' if ($self->getValue('disableRichEditor'));
|
||||
|
|
@ -582,6 +594,13 @@ sub indexContent {
|
|||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_edit ( )
|
||||
|
||||
Override the method from Asset.pm to change the title of the screen.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_edit {
|
||||
my $self = shift;
|
||||
return $self->session->privilege->insufficient() unless $self->canEdit;
|
||||
|
|
|
|||
|
|
@ -159,6 +159,27 @@ sub definition {
|
|||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAddToCartForm ( )
|
||||
|
||||
Returns a form to add this Sku to the cart. Used when this Sku is part of
|
||||
a shelf.
|
||||
|
||||
=cut
|
||||
|
||||
sub getAddToCartForm {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Sku');
|
||||
return
|
||||
WebGUI::Form::formHeader($session, {action => $self->getUrl})
|
||||
. WebGUI::Form::hidden( $session, {name => 'func', value => 'addToCart'})
|
||||
. WebGUI::Form::submit( $session, {value => $i18n->get('add to cart')})
|
||||
. WebGUI::Form::formFooter($session)
|
||||
;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getCart ( )
|
||||
|
|
@ -293,6 +314,7 @@ sub getThumbnailUrl {
|
|||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getVendorId ( )
|
||||
|
||||
Returns the vendorId of the vendor for this sku. Defaults to the default
|
||||
|
|
|
|||
638
lib/WebGUI/Asset/Sku/Ad.pm
Normal file
638
lib/WebGUI/Asset/Sku/Ad.pm
Normal file
|
|
@ -0,0 +1,638 @@
|
|||
package WebGUI::Asset::Sku::Ad;
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2009 Plain Black Corporation.
|
||||
-------------------------------------------------------------------
|
||||
Please read the legal notices (docs/legal.txt) and the license
|
||||
(docs/license.txt) that came with this distribution before using
|
||||
this software.
|
||||
-------------------------------------------------------------------
|
||||
http://www.plainblack.com info@plainblack.com
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Tie::IxHash;
|
||||
use base 'WebGUI::Asset::Sku';
|
||||
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;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Asset::Sku::Ad
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This Asset allows ads to be purchased via WebGUI shopping
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use WebGUI::Asset::Sku::Ad;
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
These methods are available from this class:
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition
|
||||
|
||||
Adds purchaseTemplate, manageTemplate, adSpace, priority, pricePerClick, pricePerImpression, clickDiscounts, impresisonDiscounts
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my %properties;
|
||||
tie %properties, 'Tie::IxHash';
|
||||
my $i18n = WebGUI::International->new($session, "Asset_AdSku");
|
||||
%properties = (
|
||||
purchaseTemplate => {
|
||||
tab => "display",
|
||||
fieldType => "template",
|
||||
namespace => "AdSku/Purchase",
|
||||
defaultValue => 'AldPGu0u-jm_5xK13atCSQ',
|
||||
label => $i18n->get("property purchase template"),
|
||||
hoverHelp => $i18n->get("property purchase template help"),
|
||||
},
|
||||
manageTemplate => {
|
||||
tab => "display",
|
||||
fieldType => "template",
|
||||
namespace => "AdSku/Manage",
|
||||
defaultValue => 'ohjyzab5i-yW6GOWTeDUHg',
|
||||
label => $i18n->get("property manage template"),
|
||||
hoverHelp => $i18n->get("property manage template help"),
|
||||
},
|
||||
adSpace => {
|
||||
tab => "properties",
|
||||
fieldType => "AdSpace",
|
||||
namespace => "AdSku",
|
||||
label => $i18n->get("property ad space"),
|
||||
hoverHelp => $i18n->get("property ad Space help"),
|
||||
},
|
||||
priority => {
|
||||
tab => "properties",
|
||||
defaultValue => '1',
|
||||
fieldType => "integer",
|
||||
label => $i18n->get("property priority"),
|
||||
hoverHelp => $i18n->get("property priority help"),
|
||||
},
|
||||
pricePerClick => {
|
||||
tab => "shop",
|
||||
defaultValue => '0.00',
|
||||
fieldType => "float",
|
||||
label => $i18n->get("property price per click"),
|
||||
hoverHelp => $i18n->get("property price per click help"),
|
||||
},
|
||||
pricePerImpression => {
|
||||
tab => "shop",
|
||||
defaultValue => '0.00',
|
||||
fieldType => "float",
|
||||
label => $i18n->get("property price per impression"),
|
||||
hoverHelp => $i18n->get("property price per impression help"),
|
||||
},
|
||||
clickDiscounts => {
|
||||
tab => "shop",
|
||||
fieldType => 'textarea',
|
||||
label => $i18n->get('property click discounts'),
|
||||
hoverHelp => $i18n->get('property click discounts help'),
|
||||
defaultValue => '',
|
||||
},
|
||||
impressionDiscounts => {
|
||||
tab => "shop",
|
||||
fieldType => 'textarea',
|
||||
label => $i18n->get('property impression discounts'),
|
||||
hoverHelp => $i18n->get('property impression discounts help'),
|
||||
defaultValue => '',
|
||||
},
|
||||
);
|
||||
|
||||
# Show the karma field only if karma is enabled
|
||||
if ($session->setting->get("useKarma")) {
|
||||
$properties{ karma } = {
|
||||
type => 'integer',
|
||||
label => $i18n->get('property adsku karma'),
|
||||
hoverHelp => $i18n->get('property adsku karma description'),
|
||||
defaultvalue => 0,
|
||||
};
|
||||
}
|
||||
|
||||
push(@{$definition}, {
|
||||
assetName => $i18n->get('assetName'),
|
||||
icon => 'adsku.gif',
|
||||
autoGenerateForms => 1,
|
||||
tableName => 'AdSku',
|
||||
className => 'WebGUI::Asset::Sku::AdSku',
|
||||
properties => \%properties,
|
||||
});
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAddToCartForm
|
||||
|
||||
Returns an empty string, since the add to cart form is complex.
|
||||
|
||||
=cut
|
||||
|
||||
sub getAddToCartForm {
|
||||
return '';
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getClickDiscountText
|
||||
|
||||
returns the text to display the number of clicks purchasaed where discounts apply
|
||||
|
||||
=cut
|
||||
|
||||
sub getClickDiscountText {
|
||||
my $self = shift;
|
||||
return getDiscountText($self->i18n->get('click discount'),
|
||||
$self->get('clickDiscounts'));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getConfiguredTitle
|
||||
|
||||
combines the adSKu title with the customers ad title
|
||||
|
||||
=cut
|
||||
|
||||
sub getConfiguredTitle {
|
||||
my $self = shift;
|
||||
return $self->get('title') . ' (' . $self->getOptions->{'adtitle'} . ')';
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getDiscountAmount -- class level function
|
||||
|
||||
returns the amount of discount to apply to this purchase
|
||||
|
||||
=cut
|
||||
|
||||
sub getDiscountAmount {
|
||||
my($discounts,$count) = @_;
|
||||
my @discounts = parseDiscountText( $discounts );
|
||||
my $previousDiscount = 0;
|
||||
foreach my $discountSet ( @discounts ) {
|
||||
last if $count < $discountSet->[1];
|
||||
$previousDiscount = $discountSet->[0];
|
||||
}
|
||||
return $previousDiscount;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getDiscountText -- class level function
|
||||
|
||||
returns a string with a coma seperated list of counts from the discount text
|
||||
|
||||
=cut
|
||||
|
||||
sub getDiscountText {
|
||||
my($format,$discounts) = @_;
|
||||
return sprintf( $format, join( ',', (map { $_->[1] } ( parseDiscountText( $discounts ) ) ) ) );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getImpressionDiscountText
|
||||
|
||||
returns the text to display the number of impressions purchased where discounts apply
|
||||
|
||||
=cut
|
||||
|
||||
sub getImpressionDiscountText {
|
||||
my $self = shift;
|
||||
return getDiscountText($self->i18n->get('impression discount'),
|
||||
$self->get('impressionDiscounts'));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getPrice
|
||||
|
||||
get the price for this purchase
|
||||
|
||||
=cut
|
||||
|
||||
sub getPrice {
|
||||
my $self = shift;
|
||||
my $options = $self->getOptions;
|
||||
my $impressionCount = $options->{impressions} || $self->{formImpressions};
|
||||
my $clickCount = $options->{clicks};
|
||||
my $impressionDiscount = getDiscountAmount($self->get('impressionDiscounts'),$impressionCount );
|
||||
my $clickDiscount = getDiscountAmount($self->get('clickDiscounts'),$clickCount );
|
||||
my $impressionPrice = $self->get('pricePerImpression') * ( 100 - $impressionDiscount ) / 100 ;
|
||||
my $clickPrice = $self->get('pricePerClick') * ( 100 - $clickDiscount ) / 100 ;
|
||||
return sprintf "%.2f", $impressionPrice * $impressionCount + $clickPrice * $clickCount;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 i18n
|
||||
|
||||
returns an internationalization object for this class
|
||||
|
||||
=cut
|
||||
|
||||
sub i18n {
|
||||
my $self = shift;
|
||||
return WebGUI::International->new($self->session, "Asset_AdSku");
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 manage
|
||||
|
||||
generate template vars for manage page
|
||||
|
||||
=cut
|
||||
|
||||
sub manage {
|
||||
my ($self) = @_;
|
||||
my $session = $self->session;
|
||||
|
||||
my $i18n = WebGUI::International->new($session, "Asset_AdSku");
|
||||
my %var;
|
||||
$var{purchaseLink} = $self->getUrl;
|
||||
my $iterator = WebGUI::AssetCollateral::Sku::Ad::Ad->getAllIterator($session,{
|
||||
constraints => [ { "adSkuPurchase.userId = ?" => $self->session->user->userId } ],
|
||||
orderBy => 'dateOfPurchase',
|
||||
});
|
||||
my %ads;
|
||||
while( my $object = $iterator->() ) {
|
||||
next if $object->get('isDeleted');
|
||||
next if exists $ads{$object->get('adId')};
|
||||
my $ad = $ads{$object->get('adId')} = WebGUI::AdSpace::Ad->new($session,$object->get('adId'));
|
||||
push @{$var{myAds}}, {
|
||||
rowTitle => $ad->get('title'),
|
||||
rowClicks => $ad->get('clicks') . '/' . $ad->get('clicksBought'),
|
||||
rowImpressions => $ad->get('impressions') . '/' . $ad->get('impressionsBought'),
|
||||
rowRenewLink => $self->getUrl('func=renew;Id=' . $object->get('adSkuPurchaseId') ),
|
||||
};
|
||||
}
|
||||
return $self->processTemplate(\%var,undef,$self->{_viewTemplate});
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 onCompletePurchase
|
||||
|
||||
inserts the ad into the adspace...
|
||||
|
||||
=cut
|
||||
|
||||
sub onCompletePurchase {
|
||||
my $self = shift;
|
||||
my $item = shift;
|
||||
my $options = $self->getOptions;
|
||||
my $ad;
|
||||
|
||||
# LATER: if we use Temp Storage for the image we need to move it to perm storage
|
||||
|
||||
if( $options->{adId} ne '' ) {
|
||||
$ad = WebGUI::AdSpace::Ad->new($self->session,$options->{adId});
|
||||
my $clicks = $options->{clicks} + $ad->get('clicksBought');
|
||||
my $impressions = $options->{impressions} + $ad->get('impressionsBought');
|
||||
$ad->set({
|
||||
title => $options->{'adtitle'},
|
||||
clicksBought => $clicks,
|
||||
impressionsBought => $impressions,
|
||||
url => $options->{'link'},
|
||||
storageId => $options->{'image'},
|
||||
});
|
||||
} else {
|
||||
$ad = WebGUI::AdSpace::Ad->create($self->session,$self->get('adSpace'),{
|
||||
title => $options->{'adtitle'},
|
||||
clicksBought => $options->{'clicks'},
|
||||
impressionsBought => $options->{'impressions'},
|
||||
url => $options->{'link'},
|
||||
storageId => $options->{'image'},
|
||||
ownerUserId => $self->session->user->userId,
|
||||
isActive => 1,
|
||||
type => 'image',
|
||||
priority => $self->get('priority'),
|
||||
adSpace => $self->get('adSpace'),
|
||||
});
|
||||
}
|
||||
|
||||
WebGUI::AssetCollateral::Sku::Ad::Ad->create($self->session,{
|
||||
userId => $item->transaction->get('userId'),
|
||||
transactionItemId => $item->getId,
|
||||
adId => $ad->getId,
|
||||
clicksPurchased => $options->{'clicks'},
|
||||
impressionsPurchased => $options->{'impressions'},
|
||||
dateOfPurchase => $item->transaction->get('dateOfPurchase'),
|
||||
storedImage => $options->{'image'},
|
||||
isDeleted => 0,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 onRemoveFromCart
|
||||
|
||||
deletes the image if it gets removed from the cart
|
||||
|
||||
LATER: if we switch to using Temp Storage we do not need to do this.
|
||||
|
||||
=cut
|
||||
|
||||
sub onRemoveFromCart {
|
||||
my $self = shift;
|
||||
my $item = shift;
|
||||
my $options = $self->getOptions;
|
||||
WebGUI::Storage->get($self->session,$options->{'image'})->delete;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 onRefund
|
||||
|
||||
delete the add if it gets refunded
|
||||
|
||||
=cut
|
||||
|
||||
sub onRefund {
|
||||
my $self = shift;
|
||||
my $item = shift;
|
||||
|
||||
my $iterator = WebGUI::AssetCollateral::Sku::Ad::Ad->getAllIterator($self->session,{
|
||||
constraints => [ { "transactionItemId = ?" => $item->getId } ],
|
||||
});
|
||||
my $crud = $iterator->();
|
||||
|
||||
my $ad = WebGUI::AdSpace::Ad->new($self->session,$crud->get('adId'));
|
||||
my $clicks = $ad->get('clicksBought') - $crud->get('clicksPurchased');
|
||||
my $impressions = $ad->get('impressionsBought') - $crud->get('impressionsPurchased') ;
|
||||
$ad->set({
|
||||
clicksBought => $clicks,
|
||||
impressionsBought => $impressions,
|
||||
});
|
||||
|
||||
$crud->delete;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 parseDiscountText -- class level function
|
||||
|
||||
returns an array of array ref's that are extracted from the discount description text
|
||||
|
||||
=cut
|
||||
|
||||
sub parseDiscountText {
|
||||
my $discountDescription = shift;
|
||||
my @lines = split "\n", $discountDescription;
|
||||
my @discounts;
|
||||
foreach my $line ( @lines ) {
|
||||
if( $line =~ /^(\d+)\@(\d+)/ ) {
|
||||
push @discounts, [ $1, $2 ];
|
||||
}
|
||||
}
|
||||
return sort { $a->[1] <=> $b->[1] } @discounts;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 prepareManage
|
||||
|
||||
Prepares the template.
|
||||
|
||||
=cut
|
||||
|
||||
sub prepareManage {
|
||||
my $self = shift;
|
||||
$self->SUPER::prepareView();
|
||||
my $templateId = $self->get("manageTemplate");
|
||||
my $template = WebGUI::Asset::Template->new($self->session, $templateId);
|
||||
$template->prepare($self->getMetaDataAsTemplateVariables);
|
||||
$self->{_viewTemplate} = $template;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 prepareView
|
||||
|
||||
Prepares the template.
|
||||
|
||||
=cut
|
||||
|
||||
sub prepareView {
|
||||
my $self = shift;
|
||||
$self->SUPER::prepareView();
|
||||
my $templateId = $self->get("purchaseTemplate");
|
||||
my $template = WebGUI::Asset::Template->new($self->session, $templateId);
|
||||
$template->prepare($self->getMetaDataAsTemplateVariables);
|
||||
$self->{_viewTemplate} = $template;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 view
|
||||
|
||||
Displays the purchase adspace form
|
||||
|
||||
=cut
|
||||
|
||||
sub view {
|
||||
my ($self) = @_;
|
||||
my $session = $self->session;
|
||||
my $options = $self->getOptions();
|
||||
|
||||
my $i18n = WebGUI::International->new($session, "Asset_AdSku");
|
||||
my %var = (
|
||||
formHeader => WebGUI::Form::formHeader($session, { action=>$self->getUrl })
|
||||
. WebGUI::Form::hidden( $session, { name=>"func", value=>"addToCart" }),
|
||||
formFooter => WebGUI::Form::formFooter($session),
|
||||
formSubmit => WebGUI::Form::submit( $session, { value => $i18n->get("form purchase button") }),
|
||||
error_msg => $options->{error_msg},
|
||||
hasAddedToCart => $self->{_hasAddedToCart},
|
||||
continueShoppingUrl => $self->getUrl,
|
||||
manageLink => $self->getUrl("func=manage"),
|
||||
adSkuTitle => $self->get('title'),
|
||||
adSkuDescription => $self->get('description'),
|
||||
formTitle => WebGUI::Form::text($session, {
|
||||
-name=>"formTitle",
|
||||
-value=>$options->{adtitle},
|
||||
-size=>40
|
||||
-default=>'untitled',
|
||||
}),
|
||||
formLink => WebGUI::Form::Url($session, {
|
||||
-name=>"formLink",
|
||||
-value=>$options->{link},
|
||||
-size=>40
|
||||
-required=>1,
|
||||
}),
|
||||
formImage => WebGUI::Form::File($session, {
|
||||
-name=>"formImage",
|
||||
-value=>$options->{image},
|
||||
-size=>40
|
||||
-forceImageOnly=>1,
|
||||
}),
|
||||
formClicks => WebGUI::Form::Integer($session, {
|
||||
-name=>"formClicks",
|
||||
-value=>$options->{clicks},
|
||||
-size=>40
|
||||
-required=>1,
|
||||
}),
|
||||
formImpressions => WebGUI::Form::Integer($session, {
|
||||
-name=>"formImpressions",
|
||||
-value=>$options->{impressions},
|
||||
-size=>40
|
||||
-required=>1,
|
||||
}),
|
||||
formAdId => WebGUI::Form::Hidden($session, {
|
||||
-name=>"formAdId",
|
||||
-value=>$options->{adId} || '',
|
||||
}),
|
||||
clickPrice => $self->get('pricePerClick'),
|
||||
impressionPrice => $self->get('pricePerImpression'),
|
||||
clickDiscount => $self->getClickDiscountText,
|
||||
impressionDiscount => $self->getImpressionDiscountText,
|
||||
);
|
||||
return $self->processTemplate(\%var,undef,$self->{_viewTemplate});
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_addToCart
|
||||
|
||||
Add this subscription to the cart.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_addToCart {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $i18n = $self->i18n;
|
||||
if ($self->canView) {
|
||||
my $form = $session->form;
|
||||
my @errors;
|
||||
#my $imageStorage = $self->getOptions->{image} || WebGUI::Storage->create($session); # LATER should be createTemp
|
||||
my $imageStorageId = $form->process('formImage', 'image'); # , $self->getOptions->{image});
|
||||
my $imageStorage = WebGUI::Storage->get($session,$imageStorageId);
|
||||
my $code;
|
||||
if( not defined $imageStorage ) { $code = 1; }
|
||||
elsif( $imageStorage->getErrorCount > 0 ) { $code = 2; }
|
||||
elsif( scalar(@{$imageStorage->getFiles}) == 0 ) { $code = 3; }
|
||||
elsif( $imageStorage->isImage((@{$imageStorage->getFiles})[0]) ) { $code = 4; }
|
||||
if( not defined $imageStorage
|
||||
or $imageStorage->getErrorCount > 0
|
||||
or scalar(@{$imageStorage->getFiles}) == 0
|
||||
# or $imageStorage->isImage((@{$imageStorage->getFiles})[0]) # not currently working
|
||||
) {
|
||||
push @errors, $i18n->get('form error no image') . $code . eval { (@{$imageStorage->getFiles})[0] } ;
|
||||
}
|
||||
my $title = $form->process('formTitle');
|
||||
if($title eq '' ) {
|
||||
push @errors, $i18n->get('form error no title');
|
||||
}
|
||||
my $link = $form->process('formLink','url');
|
||||
if($link eq '' ) {
|
||||
push @errors, $i18n->get('form error no link');
|
||||
}
|
||||
my $adId = $self->get('adSpace');
|
||||
my $adSpace = WebGUI::AdSpace->new($session,$adId);
|
||||
my $clicks = $form->process('formClicks','integer');
|
||||
if($clicks < $adSpace->get('minimumClicks') ) {
|
||||
push @errors, sprintf($i18n->get('form error min clicks'), $adSpace->get('minimumClicks'));
|
||||
}
|
||||
my $impressions = $form->process('formImpressions','integer');
|
||||
if($impressions < $adSpace->get('minimumImpressions') ) {
|
||||
push @errors, sprintf($i18n->get('form error min impressions'), $adSpace->get('minimumImpressions'));
|
||||
}
|
||||
if( @errors == 0 ) {
|
||||
$self->{_hasAddedToCart} = 1;
|
||||
$self->addToCart({
|
||||
adtitle => $title,
|
||||
link => $link,
|
||||
clicks => $clicks,
|
||||
impressions => $impressions,
|
||||
adId => $adId,
|
||||
image => $imageStorageId,
|
||||
});
|
||||
} else {
|
||||
$self->applyOptions({
|
||||
adtitle => $title,
|
||||
link => $link,
|
||||
clicks => $clicks,
|
||||
impressions => $impressions,
|
||||
adId => $adId,
|
||||
image => $imageStorageId,
|
||||
error_msg => join( '<br>', @errors ),
|
||||
});
|
||||
}
|
||||
}
|
||||
return $self->www_view;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_manage
|
||||
|
||||
manage previously purchased ads
|
||||
|
||||
=cut
|
||||
|
||||
sub www_manage {
|
||||
my $self = shift;
|
||||
my $check = $self->checkView;
|
||||
return $check if (defined $check);
|
||||
$self->session->http->setLastModified($self->getContentLastModified);
|
||||
$self->session->http->sendHeader;
|
||||
$self->prepareManage;
|
||||
my $style = $self->processStyle($self->getSeparator);
|
||||
my ($head, $foot) = split($self->getSeparator,$style);
|
||||
$self->session->output->print($head, 1);
|
||||
$self->session->output->print($self->manage);
|
||||
$self->session->output->print($foot, 1);
|
||||
return "chunked";
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_renew
|
||||
|
||||
renew an ad
|
||||
|
||||
=cut
|
||||
|
||||
sub www_renew {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $id = $session->form->get('Id');
|
||||
my $crud = WebGUI::AssetCollateral::Sku::Ad::Ad->new($session,$id);
|
||||
my $ad = WebGUI::AdSpace::Ad->new($session,$crud->get('adId'));
|
||||
$self->applyOptions({
|
||||
adtitle => $ad->get('title'),
|
||||
clicks => $crud->get('clicksPurchased'),
|
||||
impressions => $crud->get('impressionsPurchased'),
|
||||
link => $ad->get('url'),
|
||||
image => $ad->get('storageId'),
|
||||
adId => $crud->get('adId'),
|
||||
});
|
||||
return $self->www_view;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
|
@ -92,6 +92,28 @@ sub definition {
|
|||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAddToCartForm ( )
|
||||
|
||||
Returns a form to add this Sku to the cart. Used when this Sku is part of
|
||||
a shelf. Overrode master class to add price form.
|
||||
|
||||
=cut
|
||||
|
||||
sub getAddToCartForm {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Donation');
|
||||
return
|
||||
WebGUI::Form::formHeader($session, {action => $self->getUrl})
|
||||
. WebGUI::Form::hidden( $session, {name => 'func', value => 'donate'})
|
||||
. WebGUI::Form::float( $session, {name => 'price', defaultValue => $self->getPrice })
|
||||
. WebGUI::Form::submit( $session, {value => $i18n->get('donate button')})
|
||||
. WebGUI::Form::formFooter($session)
|
||||
;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getConfiguredTitle
|
||||
|
|
@ -162,18 +184,21 @@ sub view {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 wwww_donate
|
||||
=head2 www_donate
|
||||
|
||||
Accepts the information from the donation form and adds it to the cart.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_donate {
|
||||
my $self = shift;
|
||||
if ($self->canView) {
|
||||
my $self = shift;
|
||||
my $price = $self->session->form->get("price") || $self->getPrice;
|
||||
|
||||
if ($self->canView && $price > 0) {
|
||||
$self->{_hasAddedToCart} = 1;
|
||||
$self->addToCart({price => ($self->session->form->get("price") || $self->getPrice) });
|
||||
$self->addToCart( { price => $price } );
|
||||
}
|
||||
|
||||
return $self->www_view;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -165,6 +165,26 @@ sub drawRelatedBadgeGroupsField {
|
|||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAddToCartForm
|
||||
|
||||
Returns a button to take the user to the view screen.
|
||||
|
||||
=cut
|
||||
|
||||
sub getAddToCartForm {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Sku');
|
||||
return
|
||||
WebGUI::Form::formHeader($session, {action => $self->getUrl})
|
||||
. WebGUI::Form::hidden( $session, {name => 'func', value => 'view'})
|
||||
. WebGUI::Form::submit( $session, {value => $i18n->get('see more')})
|
||||
. WebGUI::Form::formFooter($session)
|
||||
;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getConfiguredTitle
|
||||
|
|
|
|||
|
|
@ -83,6 +83,26 @@ sub definition {
|
|||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAddToCartForm
|
||||
|
||||
Returns a button to take the user to the view screen.
|
||||
|
||||
=cut
|
||||
|
||||
sub getAddToCartForm {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Sku');
|
||||
return
|
||||
WebGUI::Form::formHeader($session, {action => $self->getUrl})
|
||||
. WebGUI::Form::hidden( $session, {name => 'func', value => 'view'})
|
||||
. WebGUI::Form::submit( $session, {value => $i18n->get('see more')})
|
||||
. WebGUI::Form::formFooter($session)
|
||||
;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getConfiguredTitle
|
||||
|
|
|
|||
|
|
@ -229,6 +229,25 @@ sub drawRelatedRibbonsField {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAddToCartForm
|
||||
|
||||
Returns a button to take the user to the view screen.
|
||||
|
||||
=cut
|
||||
|
||||
sub getAddToCartForm {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Sku');
|
||||
return
|
||||
WebGUI::Form::formHeader($session, {action => $self->getUrl})
|
||||
. WebGUI::Form::hidden( $session, {name => 'func', value => 'view'})
|
||||
. WebGUI::Form::submit( $session, {value => $i18n->get('see more')})
|
||||
. WebGUI::Form::formFooter($session)
|
||||
;}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getConfiguredTitle
|
||||
|
||||
Returns title + badgeholder name.
|
||||
|
|
|
|||
|
|
@ -76,6 +76,26 @@ sub definition {
|
|||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAddToCartForm
|
||||
|
||||
Returns a button to take the user to the view screen.
|
||||
|
||||
=cut
|
||||
|
||||
sub getAddToCartForm {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Sku');
|
||||
return
|
||||
WebGUI::Form::formHeader($session, {action => $self->getUrl})
|
||||
. WebGUI::Form::hidden( $session, {name => 'func', value => 'view'})
|
||||
. WebGUI::Form::submit( $session, {value => $i18n->get('see more')})
|
||||
. WebGUI::Form::formFooter($session)
|
||||
;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getConfiguredTitle
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ sub view {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 wwww_addToCart
|
||||
=head2 www_addToCart
|
||||
|
||||
Accepts the information from the form and adds it to the cart.
|
||||
|
||||
|
|
|
|||
|
|
@ -240,6 +240,37 @@ sub duplicate {
|
|||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAddToCartForm ( )
|
||||
|
||||
Returns a form to add this Sku to the cart. Used when this Sku is part of
|
||||
a shelf. Overrode master class to add variant dropdown.
|
||||
|
||||
=cut
|
||||
|
||||
sub getAddToCartForm {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Product');
|
||||
my %variants = ();
|
||||
tie %variants, 'Tie::IxHash';
|
||||
foreach my $collateral ( @{ $self->getAllCollateral('variantsJSON')} ) {
|
||||
$variants{$collateral->{variantId}} = join ", ", $collateral->{shortdesc}, sprintf('%.2f',$collateral->{price});
|
||||
}
|
||||
return
|
||||
WebGUI::Form::formHeader($session, {action => $self->getUrl})
|
||||
. WebGUI::Form::hidden( $session, {name => 'func', value => 'buy'})
|
||||
. WebGUI::Form::selectBox( $session, {
|
||||
name => 'vid',
|
||||
options => \%variants,
|
||||
value => [0],
|
||||
})
|
||||
. WebGUI::Form::submit( $session, {value => $i18n->get('add to cart')})
|
||||
. WebGUI::Form::formFooter($session)
|
||||
;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAllCollateral ( tableName )
|
||||
|
|
|
|||
|
|
@ -269,6 +269,27 @@ sub generateSubscriptionCodeBatch {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAddToCartForm ( )
|
||||
|
||||
Returns a form to add this Sku to the cart. Used when this Sku is part of
|
||||
a shelf. Override master class to add different form.
|
||||
|
||||
=cut
|
||||
|
||||
sub getAddToCartForm {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Subscription');
|
||||
return
|
||||
WebGUI::Form::formHeader($session, {action => $self->getUrl})
|
||||
. WebGUI::Form::hidden( $session, {name => 'func', value => 'purchaseSubscription'})
|
||||
. WebGUI::Form::submit( $session, {value => $i18n->get('purchase button')})
|
||||
. WebGUI::Form::formFooter($session)
|
||||
;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAdminConsoleWithSubmenu ( )
|
||||
|
||||
Returns an admin console with management links added to the submenu.
|
||||
|
|
@ -933,7 +954,7 @@ sub www_listSubscriptionCodes {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 wwww_purchaseSubscription
|
||||
=head2 www_purchaseSubscription
|
||||
|
||||
Add this subscription to the cart.
|
||||
|
||||
|
|
|
|||
|
|
@ -191,6 +191,18 @@ sub purgeCache {
|
|||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 view ( $calledAsWebMethod )
|
||||
|
||||
Override the base class to implement caching, template and macro processing.
|
||||
|
||||
=head3 $calledAsWebMethod
|
||||
|
||||
If this is true, then change the cache method, and do not display the
|
||||
toolbar if in adminMode.
|
||||
|
||||
=cut
|
||||
|
||||
sub view {
|
||||
my $self = shift;
|
||||
my $calledAsWebMethod = shift;
|
||||
|
|
@ -216,15 +228,6 @@ sub view {
|
|||
return $output;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_edit {
|
||||
my $self = shift;
|
||||
return $self->session->privilege->insufficient() unless $self->canEdit;
|
||||
return $self->session->privilege->locked() unless $self->canEditIfLocked;
|
||||
return $self->getAdminConsole->render($self->getEditForm->print,$self->addEditLabel);
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_view
|
||||
|
|
@ -234,12 +237,12 @@ A web accessible version of the view method.
|
|||
=cut
|
||||
|
||||
sub www_view {
|
||||
my $self = shift;
|
||||
return $self->session->privilege->insufficient() unless $self->canView;
|
||||
my $mimeType=$self->getValue('mimeType');
|
||||
$self->session->http->setMimeType($mimeType || 'text/html');
|
||||
$self->session->http->setCacheControl($self->get("cacheTimeout"));
|
||||
return $self->view(1);
|
||||
my $self = shift;
|
||||
return $self->session->privilege->insufficient() unless $self->canView;
|
||||
my $mimeType=$self->getValue('mimeType');
|
||||
$self->session->http->setMimeType($mimeType || 'text/html');
|
||||
$self->session->http->setCacheControl($self->get("cacheTimeout"));
|
||||
return $self->view(1);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ sub getEditForm {
|
|||
formContent => WebGUI::Form::HTMLArea($session, { name => 'content', richEditId => $wiki->get('richEditor'), value => $self->get('content') }) ,
|
||||
formSubmit => WebGUI::Form::submit($session, { value => 'Save' }),
|
||||
formProtect => WebGUI::Form::yesNo($session, { name => "isProtected", value=>$self->getValue("isProtected")}),
|
||||
formKeywords => WebGUI::Form::text($session, {
|
||||
formKeywords => WebGUI::Form::keywords($session, {
|
||||
name => "keywords",
|
||||
value => WebGUI::Keyword->new($session)->getKeywordsForAsset({asset=>$self}),
|
||||
}),
|
||||
|
|
|
|||
338
lib/WebGUI/Asset/Wobject/Carousel.pm
Normal file
338
lib/WebGUI/Asset/Wobject/Carousel.pm
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
package WebGUI::Asset::Wobject::Carousel;
|
||||
|
||||
$VERSION = "1.0.0";
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# WebGUI is Copyright 2001-2008 Plain Black Corporation.
|
||||
#-------------------------------------------------------------------
|
||||
# Please read the legal notices (docs/legal.txt) and the license
|
||||
# (docs/license.txt) that came with this distribution before using
|
||||
# this software.
|
||||
#-------------------------------------------------------------------
|
||||
# http://www.plainblack.com info@plainblack.com
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use JSON;
|
||||
use Tie::IxHash;
|
||||
use WebGUI::International;
|
||||
use WebGUI::Utility;
|
||||
use base 'WebGUI::Asset::Wobject';
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( )
|
||||
|
||||
defines wobject properties for New Wobject instances. You absolutely need
|
||||
this method in your new Wobjects. If you choose to "autoGenerateForms", the
|
||||
getEditForm method is unnecessary/redundant/useless.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_Carousel');
|
||||
my %properties;
|
||||
tie %properties, 'Tie::IxHash';
|
||||
%properties = (
|
||||
templateId =>{
|
||||
fieldType =>"template",
|
||||
defaultValue =>'CarouselTmpl0000000002',
|
||||
tab =>"display",
|
||||
noFormPost =>0,
|
||||
namespace =>"Carousel",
|
||||
hoverHelp =>$i18n->get('carousel template description'),
|
||||
label =>$i18n->get('carousel template label'),
|
||||
},
|
||||
items =>{
|
||||
noFormPost =>1,
|
||||
fieldType =>'text',
|
||||
autoGenerate =>0,
|
||||
},
|
||||
);
|
||||
push(@{$definition}, {
|
||||
assetName=>$i18n->get('assetName'),
|
||||
icon=>'Carousel.png',
|
||||
autoGenerateForms=>1,
|
||||
tableName=>'Carousel',
|
||||
className=>'WebGUI::Asset::Wobject::Carousel',
|
||||
properties=>\%properties
|
||||
});
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 duplicate ( )
|
||||
|
||||
duplicates a New Wobject. This method is unnecessary, but if you have
|
||||
auxiliary, ancillary, or "collateral" data or files related to your
|
||||
wobject instances, you will need to duplicate them here.
|
||||
|
||||
=cut
|
||||
|
||||
sub duplicate {
|
||||
my $self = shift;
|
||||
my $newAsset = $self->SUPER::duplicate(@_);
|
||||
return $newAsset;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getEditForm ( )
|
||||
|
||||
returns the tabform object that will be used in generating the edit page for New Wobjects.
|
||||
This method is optional if you set autoGenerateForms=1 in the definition.
|
||||
|
||||
=cut
|
||||
|
||||
sub getEditForm {
|
||||
my $self = shift;
|
||||
my $tabform = $self->SUPER::getEditForm();
|
||||
my $i18n = WebGUI::International->new($self->session, "Asset_Carousel");
|
||||
|
||||
$self->session->style->setScript($self->session->url->extras('yui/build/editor/editor-min.js'), {type =>
|
||||
'text/javascript'});
|
||||
$self->session->style->setLink($self->session->url->extras('yui/build/editor/assets/skins/sam/editor.css'), {type
|
||||
=>'text/css', rel=>'stylesheet'});
|
||||
$self->session->style->setScript($self->session->url->extras('wobject/Carousel/carousel.js'), {type =>
|
||||
'text/javascript'});
|
||||
|
||||
my $tableRowStart =
|
||||
'<tr id="items_row">'
|
||||
.' <td class="formDescription" valign="top" style="width: 180px;"><label for="item1">'
|
||||
.$i18n->get("items label").'</label><div class="wg-hoverhelp">'.$i18n->get("items description").'</div></td>'
|
||||
.' <td id="items_td" valign="top" class="tableData">'
|
||||
.' <input type="button" value="Add item" onClick="javascript:addItem()"></button><br /><br />';
|
||||
|
||||
$tabform->getTab("properties")->raw($tableRowStart);
|
||||
|
||||
if($self->getValue('items')){
|
||||
my @items = @{JSON->new->decode($self->getValue('items'))->{items}};
|
||||
|
||||
foreach my $item (@items){
|
||||
my $itemHTML = $i18n->get("id label").'<div class="wg-hoverhelp">'.$i18n->get("id description").'</div>: '
|
||||
.'<input type="text" id="itemId'.$item->{sequenceNumber}.'" '
|
||||
.'name="itemId_'.$item->{sequenceNumber}.'" value="'.$item->{itemId}.'">'
|
||||
.'<textarea id="item'.$item->{sequenceNumber}.'" name="item_'.$item->{sequenceNumber}.'" '
|
||||
.'class="carouselItemText" rows="#" cols="#" '
|
||||
.'style="width: 500px; height: 80px;">'.$item->{text}."</textarea><br />\n";
|
||||
|
||||
$itemHTML .=
|
||||
" <script type='text/javascript'>\n"
|
||||
.'var myEditor'.$item->{sequenceNumber}.' '
|
||||
.'= new YAHOO.widget.SimpleEditor("item'.$item->{sequenceNumber}.'", '
|
||||
."{height: '80px', width: '500px', handleSubmit: true});\n"
|
||||
.'myEditor'.$item->{sequenceNumber}.".render()\n"
|
||||
."</script>\n";
|
||||
$tabform->getTab("properties")->raw($itemHTML);
|
||||
}
|
||||
}
|
||||
else{
|
||||
my $itemHTML = 'ID: <input type="text" id="itemId1" name="itemId_1" value="carousel_item_1">'
|
||||
.'<textarea id="item1" name="item_1" class="carouselItemText" rows="#" cols="#" '
|
||||
."style='width: 500px; height: 80px;'></textarea><br />\n";
|
||||
|
||||
$itemHTML .=
|
||||
"<script type='text/javascript'>\n"
|
||||
."var myEditor1 = new YAHOO.widget.SimpleEditor('item1', {height: '80px', width: '500px', handleSubmit: true});\n"
|
||||
."myEditor1.render()\n"
|
||||
."</script>\n";
|
||||
$tabform->getTab("properties")->raw($itemHTML);
|
||||
}
|
||||
my $tableRowEnd = qq|
|
||||
</td>
|
||||
</tr>
|
||||
|;
|
||||
$tabform->getTab("properties")->raw($tableRowEnd);
|
||||
|
||||
return $tabform;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 prepareView ( )
|
||||
|
||||
See WebGUI::Asset::prepareView() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub prepareView {
|
||||
my $self = shift;
|
||||
$self->SUPER::prepareView();
|
||||
#$self->session->errorHandler->warn('templateId: '.$self->get("parentId"));
|
||||
my $template = WebGUI::Asset::Template->new($self->session, $self->get("templateId"));
|
||||
$template->prepare;
|
||||
$self->{_viewTemplate} = $template;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 processPropertiesFromFormPost ( )
|
||||
|
||||
Used to process properties from the form posted.
|
||||
|
||||
=cut
|
||||
|
||||
sub processPropertiesFromFormPost {
|
||||
my $self = shift;
|
||||
my $form = $self->session->form;
|
||||
my (@items,$items);
|
||||
$self->SUPER::processPropertiesFromFormPost(@_);
|
||||
|
||||
foreach my $param ($form->param) {
|
||||
if ($param =~ m/^item_/){
|
||||
my $sequenceNumber = $param;
|
||||
$sequenceNumber =~ s/^item_//;
|
||||
if($form->process('itemId_'.$sequenceNumber)){
|
||||
push(@items,{
|
||||
sequenceNumber => $sequenceNumber,
|
||||
text => $form->process($param),
|
||||
itemId => $form->process('itemId_'.$sequenceNumber),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my @sortedItems = sort { $a->{sequenceNumber} cmp $b->{sequenceNumber} } @items;
|
||||
@items = ();
|
||||
for (my $i=0; $i<scalar @sortedItems; $i++) {
|
||||
$sortedItems[$i]->{sequenceNumber} = $i + 1;
|
||||
push(@items,$sortedItems[$i]);
|
||||
}
|
||||
|
||||
$items = JSON->new->encode({items => \@items});
|
||||
$self->update({items => $items});
|
||||
return undef;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 purge ( )
|
||||
|
||||
removes collateral data associated with a Carousel when the system
|
||||
purges it's data. This method is unnecessary, but if you have
|
||||
auxiliary, ancillary, or "collateral" data or files related to your
|
||||
wobject instances, you will need to purge them here.
|
||||
|
||||
=cut
|
||||
|
||||
sub purge {
|
||||
my $self = shift;
|
||||
#purge your wobject-specific data here. This does not include fields
|
||||
# you create for your Carousel asset/wobject table.
|
||||
return $self->SUPER::purge;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 view ( )
|
||||
|
||||
method called by the www_view method. Returns a processed template
|
||||
to be displayed within the page style.
|
||||
|
||||
=cut
|
||||
|
||||
sub view {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my (@item_loop);
|
||||
|
||||
#This automatically creates template variables for all of your wobject's properties.
|
||||
my $var = $self->get;
|
||||
|
||||
if($self->getValue('items')){
|
||||
$var->{item_loop} = JSON->new->decode($self->getValue('items'))->{items};
|
||||
}
|
||||
|
||||
#This is an example of debugging code to help you diagnose problems.
|
||||
#WebGUI::ErrorHandler::warn($self->get("templateId"));
|
||||
|
||||
return $self->processTemplate($var, undef, $self->{_viewTemplate});
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_edit ( )
|
||||
|
||||
Web facing method which is the default edit page. This method is entirely
|
||||
optional. Take it out unless you specifically want to set a submenu in your
|
||||
adminConsole views.
|
||||
|
||||
=cut
|
||||
|
||||
#sub www_edit {
|
||||
# my $self = shift;
|
||||
# return $self->session->privilege->insufficient() unless $self->canEdit;
|
||||
# return $self->session->privilege->locked() unless $self->canEditIfLocked;
|
||||
# my $i18n = WebGUI::International->new($self->session, "Asset_Carousel");
|
||||
# return $self->getAdminConsole->render($self->getEditForm->print, $i18n->get("edit title"));
|
||||
#}
|
||||
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# Everything below here is to make it easier to install your custom
|
||||
# wobject, but has nothing to do with wobjects in general
|
||||
#-------------------------------------------------------------------
|
||||
# cd /data/WebGUI/lib
|
||||
# perl -MWebGUI::Asset::Wobject::Carousel -e install www.example.com.conf [ /path/to/WebGUI ]
|
||||
# - or -
|
||||
# perl -MWebGUI::Asset::Wobject::Carousel -e uninstall www.example.com.conf [ /path/to/WebGUI ]
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
||||
use base 'Exporter';
|
||||
our @EXPORT = qw(install uninstall);
|
||||
use WebGUI::Session;
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub install {
|
||||
my $config = $ARGV[0];
|
||||
my $home = $ARGV[1] || "/data/WebGUI";
|
||||
die "usage: perl -MWebGUI::Asset::Wobject::Carousel -e install www.example.com.conf\n" unless ($home && $config);
|
||||
print "Installing asset.\n";
|
||||
my $session = WebGUI::Session->open($home, $config);
|
||||
|
||||
my $assets = $session->config->get( "assets" );
|
||||
$assets->{ "WebGUI::Asset::Wobject::Carousel" } = { category => "utilities" };
|
||||
$session->config->set( "assets", $assets );
|
||||
#$session->config->addToArray("assets","WebGUI::Asset::Wobject::Carousel");
|
||||
$session->db->write("create table Carousel (
|
||||
assetId char(22) binary not null,
|
||||
revisionDate bigint not null,
|
||||
items mediumtext,
|
||||
templateId char(22),
|
||||
primary key (assetId, revisionDate)
|
||||
)");
|
||||
$session->var->end;
|
||||
$session->close;
|
||||
print "Done. Please restart Apache.\n";
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub uninstall {
|
||||
my $config = $ARGV[0];
|
||||
my $home = $ARGV[1] || "/data/WebGUI";
|
||||
die "usage: perl -MWebGUI::Asset::Wobject::Carousel -e uninstall www.example.com.conf\n" unless ($home && $config);
|
||||
print "Uninstalling asset.\n";
|
||||
my $session = WebGUI::Session->open($home, $config);
|
||||
$session->config->deleteFromArray("assets","WebGUI::Asset::Wobject::Carousel");
|
||||
my $rs = $session->db->read("select assetId from asset where className='WebGUI::Asset::Wobject::Carousel'");
|
||||
while (my ($id) = $rs->array) {
|
||||
my $asset = WebGUI::Asset->new($session, $id, "WebGUI::Asset::Wobject::Carousel");
|
||||
$asset->purge if defined $asset;
|
||||
}
|
||||
$session->db->write("drop table Carousel");
|
||||
$session->var->end;
|
||||
$session->close;
|
||||
print "Done. Please restart Apache.\n";
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
#vim:ft=perl
|
||||
|
|
@ -20,9 +20,9 @@ use WebGUI::Paginator;
|
|||
use WebGUI::Utility;
|
||||
use WebGUI::Asset::Wobject;
|
||||
use WebGUI::Workflow::Cron;
|
||||
use WebGUI::Asset::RSSCapable;
|
||||
use base 'WebGUI::Asset::RSSCapable';
|
||||
use base 'WebGUI::Asset::Wobject';
|
||||
use Class::C3;
|
||||
use base qw(WebGUI::AssetAspect::RssFeed WebGUI::Asset::Wobject);
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub _computePostCount {
|
||||
|
|
@ -62,27 +62,16 @@ sub _visitorCacheOk {
|
|||
&& !$self->session->form->process('sortBy'));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# encode a string to include in xml (for RSS export)
|
||||
sub _xml_encode {
|
||||
my $text = shift;
|
||||
$text =~ s/&/&/g;
|
||||
$text =~ s/</</g;
|
||||
$text =~ s/\]\]>/\]\]>/g;
|
||||
return $text;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub addChild {
|
||||
my $self = shift;
|
||||
my $properties = shift;
|
||||
my @other = @_;
|
||||
if ($properties->{className} ne "WebGUI::Asset::Post::Thread"
|
||||
and $properties->{className} ne 'WebGUI::Asset::RSSFromParent') {
|
||||
if ($properties->{className} ne "WebGUI::Asset::Post::Thread") {
|
||||
$self->session->errorHandler->security("add a ".$properties->{className}." to a ".$self->get("className"));
|
||||
return undef;
|
||||
}
|
||||
return $self->SUPER::addChild($properties, @other);
|
||||
return $self->next::method($properties, @other);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -263,7 +252,7 @@ sub canEdit {
|
|||
) &&
|
||||
$self->canStartThread( $userId )
|
||||
) || # account for new threads
|
||||
$self->SUPER::canEdit( $userId )
|
||||
$self->next::method( $userId )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -271,7 +260,7 @@ sub canEdit {
|
|||
sub canModerate {
|
||||
my $self = shift;
|
||||
my $userId = shift || $self->session->user->userId;
|
||||
return $self->SUPER::canEdit( $userId );
|
||||
return $self->WebGUI::Asset::Wobject::canEdit( $userId );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -294,7 +283,7 @@ sub canPost {
|
|||
}
|
||||
# Users who can edit the collab can post
|
||||
else {
|
||||
return $self->SUPER::canEdit( $userId );
|
||||
return $self->WebGUI::Asset::Wobject::canEdit( $userId );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -322,7 +311,7 @@ sub canStartThread {
|
|||
;
|
||||
return (
|
||||
$user->isInGroup($self->get("canStartThreadGroupId"))
|
||||
|| $self->SUPER::canEdit( $userId )
|
||||
|| $self->WebGUI::Asset::Wobject::canEdit( $userId )
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -331,13 +320,13 @@ sub canStartThread {
|
|||
sub canView {
|
||||
my $self = shift;
|
||||
my $userId = shift || $self->session->user->userId;
|
||||
return $self->SUPER::canView( $userId ) || $self->canPost( $userId );
|
||||
return $self->next::method( $userId ) || $self->canPost( $userId );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub commit {
|
||||
my $self = shift;
|
||||
$self->SUPER::commit;
|
||||
$self->next::method;
|
||||
my $cron = undef;
|
||||
if ($self->get("getMailCronId")) {
|
||||
$cron = WebGUI::Workflow::Cron->new($self->session, $self->get("getMailCronId"));
|
||||
|
|
@ -799,13 +788,13 @@ sub definition {
|
|||
className=>'WebGUI::Asset::Wobject::Collaboration',
|
||||
properties=>\%properties,
|
||||
});
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
return $class->next::method($session, $definition);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub duplicate {
|
||||
my $self = shift;
|
||||
my $newAsset = $self->SUPER::duplicate(@_);
|
||||
my $newAsset = $self->next::method(@_);
|
||||
$newAsset->createSubscriptionGroup;
|
||||
return $newAsset;
|
||||
}
|
||||
|
|
@ -821,7 +810,7 @@ Add a tab for the mail interface.
|
|||
sub getEditTabs {
|
||||
my $self = shift;
|
||||
my $i18n = WebGUI::International->new($self->session,"Asset_Collaboration");
|
||||
return ($self->SUPER::getEditTabs(), ['mail', $i18n->get('mail'), 9]);
|
||||
return ($self->next::method, ['mail', $i18n->get('mail'), 9]);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -838,7 +827,7 @@ sub getNewThreadUrl {
|
|||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub getRssItems {
|
||||
sub getRssFeedItems {
|
||||
my $self = shift;
|
||||
|
||||
# XXX copied and reformatted this query from www_viewRSS, but why is it constructed like this?
|
||||
|
|
@ -861,6 +850,7 @@ SQL
|
|||
my $datetime = $self->session->datetime;
|
||||
|
||||
my @posts;
|
||||
my $rssLimit = $self->get('itemsPerFeed');
|
||||
for my $postId (@postIds) {
|
||||
my $post = WebGUI::Asset->new($self->session, $postId, 'WebGUI::Asset::Post::Thread');
|
||||
my $postUrl = $siteUrl . $post->getUrl;
|
||||
|
|
@ -881,24 +871,26 @@ SQL
|
|||
}
|
||||
}
|
||||
|
||||
push @posts, {
|
||||
push @posts, {
|
||||
author => $post->get('username'),
|
||||
title => $post->get('title'),
|
||||
'link' => $postUrl,
|
||||
'link' => $postUrl,
|
||||
guid => $postUrl,
|
||||
description => $post->get('synopsis'),
|
||||
epochDate => $post->get('creationDate'),
|
||||
pubDate => $datetime->epochToMail($post->get('creationDate')),
|
||||
attachmentLoop => $attachmentLoop,
|
||||
attachmentLoop => $attachmentLoop,
|
||||
userDefined1 => $post->get("userDefined1"),
|
||||
userDefined2 => $post->get("userDefined2"),
|
||||
userDefined3 => $post->get("userDefined3"),
|
||||
userDefined4 => $post->get("userDefined4"),
|
||||
userDefined5 => $post->get("userDefined5"),
|
||||
};
|
||||
|
||||
last if $rssLimit <= scalar(@posts);
|
||||
}
|
||||
|
||||
return @posts;
|
||||
return \@posts;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -1064,7 +1056,7 @@ sub getViewTemplateVars {
|
|||
$var{'user.canPost'} = $self->canPost;
|
||||
$var{'user.canStartThread'} = $self->canStartThread;
|
||||
$var{"add.url"} = $self->getNewThreadUrl;
|
||||
$var{"rss.url"} = $self->getRssUrl;
|
||||
$var{"rss.url"} = $self->getRssFeedUrl;
|
||||
$var{'user.isModerator'} = $self->canModerate;
|
||||
$var{'user.isVisitor'} = ($self->session->user->isVisitor);
|
||||
$var{'user.isSubscribed'} = $self->isSubscribed;
|
||||
|
|
@ -1170,11 +1162,8 @@ See WebGUI::Asset::prepareView() for details.
|
|||
|
||||
sub prepareView {
|
||||
my $self = shift;
|
||||
$self->SUPER::prepareView();
|
||||
$self->next::method;
|
||||
my $template = WebGUI::Asset::Template->new($self->session, $self->get("collaborationTemplateId")) or die "no good: ".$self->get("collaborationTemplateId");
|
||||
if ($self->get('rssCapableRssEnabled')) {
|
||||
$self->session->style->setLink($self->getRssUrl,{ rel=>'alternate', type=>'application/rss+xml', title=>$self->get('title') . ' RSS' });
|
||||
}
|
||||
$template->prepare($self->getMetaDataAsTemplateVariables);
|
||||
$self->{_viewTemplate} = $template;
|
||||
}
|
||||
|
|
@ -1184,7 +1173,7 @@ sub prepareView {
|
|||
sub processPropertiesFromFormPost {
|
||||
my $self = shift;
|
||||
my $updatePrivs = ($self->session->form->process("groupIdView") ne $self->get("groupIdView") || $self->session->form->process("groupIdEdit") ne $self->get("groupIdEdit"));
|
||||
$self->SUPER::processPropertiesFromFormPost;
|
||||
$self->next::method;
|
||||
if ($self->get("subscriptionGroupId") eq "") {
|
||||
$self->createSubscriptionGroup;
|
||||
}
|
||||
|
|
@ -1212,7 +1201,7 @@ sub purge {
|
|||
my $cron = WebGUI::Workflow::Cron->new($self->session, $self->get("getMailCronId"));
|
||||
$cron->delete if defined $cron;
|
||||
}
|
||||
$self->SUPER::purge;
|
||||
$self->next::method;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -1227,7 +1216,7 @@ sub purgeCache {
|
|||
my $self = shift;
|
||||
WebGUI::Cache->new($self->session,"view_".$self->getId)->delete;
|
||||
WebGUI::Cache->new($self->session,$self->_visitorCacheKey)->delete;
|
||||
$self->SUPER::purgeCache;
|
||||
$self->next::method;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -1460,7 +1449,7 @@ sub www_view {
|
|||
my $self = shift;
|
||||
my $disableCache = ($self->session->form->process("sortBy") ne "");
|
||||
$self->session->http->setCacheControl($self->get("visitorCacheTimeout")) if ($self->session->user->isVisitor && !$disableCache);
|
||||
return $self->SUPER::www_view(@_);
|
||||
return $self->next::method(@_);
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -359,6 +359,14 @@ sub prepareView {
|
|||
|
||||
#------------------------------------------------------------------
|
||||
|
||||
=head2 purge ( )
|
||||
|
||||
See WebGUI::Asset::purge() for details. Extend SUPERclass
|
||||
to handle deleting tickets, tokens, ribbons, registrants, badge groups
|
||||
and event meta data.
|
||||
|
||||
=cut
|
||||
|
||||
sub purge {
|
||||
my $self = shift;
|
||||
my $db = $self->session->db;
|
||||
|
|
|
|||
|
|
@ -206,6 +206,14 @@ sub purgeCache {
|
|||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 view ( )
|
||||
|
||||
See WebGUI::Asset::view for details. Generate template variables and
|
||||
render the template. Also handles caching.
|
||||
|
||||
=cut
|
||||
|
||||
sub view {
|
||||
my $self = shift;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ package WebGUI::Asset::Wobject::Gallery;
|
|||
#-------------------------------------------------------------------
|
||||
|
||||
use strict;
|
||||
use base 'WebGUI::Asset::Wobject';
|
||||
use Class::C3;
|
||||
use base qw(WebGUI::AssetAspect::RssFeed WebGUI::Asset::Wobject);
|
||||
use JSON;
|
||||
use Tie::IxHash;
|
||||
use WebGUI::International;
|
||||
|
|
@ -338,7 +339,7 @@ sub definition {
|
|||
properties => \%properties,
|
||||
};
|
||||
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
return $class->next::method($session, $definition);
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
|
@ -366,7 +367,7 @@ sub addChild {
|
|||
return undef;
|
||||
}
|
||||
|
||||
return $self->SUPER::addChild( $properties, @_ );
|
||||
return $self->next::method( $properties, @_ );
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
|
@ -740,6 +741,41 @@ sub getPreviousAlbumId {
|
|||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getRssFeedItems ()
|
||||
|
||||
Returns an array reference of hash references. Each hash reference has a title,
|
||||
description, link, and date field. The date field can be either an epoch date, an RFC 1123
|
||||
date, or a ISO date in the format of YYYY-MM-DD HH:MM::SS. Optionally specify an
|
||||
author, and a guid field.
|
||||
|
||||
=cut
|
||||
|
||||
sub getRssFeedItems {
|
||||
my $self = shift;
|
||||
|
||||
my $p
|
||||
= $self->getAlbumPaginator( {
|
||||
perpage => $self->get('itemsPerFeed'),
|
||||
} );
|
||||
|
||||
my $var = [];
|
||||
for my $assetId ( @{ $p->getPageData } ) {
|
||||
my $asset = WebGUI::Asset::Wobject::GalleryAlbum->newPending( $self->session, $assetId );
|
||||
push @{ $var }, {
|
||||
'link' => $asset->getUrl,
|
||||
'guid' => $asset->{_properties}->{ 'assetId' },
|
||||
'title' => $asset->getTitle,
|
||||
'description' => $asset->{_properties}->{ 'description' },
|
||||
'date' => $asset->{_properties}->{ 'creationDate' },
|
||||
'author' => WebGUI::User->new($self->session, $asset->{_properties}->{ 'ownerUserId' })->username
|
||||
};
|
||||
}
|
||||
|
||||
return $var;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getSearchPaginator ( rules )
|
||||
|
|
@ -934,7 +970,7 @@ See WebGUI::Asset::prepareView() for details.
|
|||
|
||||
sub prepareView {
|
||||
my $self = shift;
|
||||
$self->SUPER::prepareView();
|
||||
$self->next::method();
|
||||
|
||||
if ( $self->get("viewDefault") eq "album" && $self->get("viewAlbumAssetId") && $self->get("viewAlbumAssetId")
|
||||
ne 'PBasset000000000000001') {
|
||||
|
|
@ -1042,7 +1078,7 @@ sub www_add {
|
|||
return $self->processStyle($i18n->get("error add uncommitted"));
|
||||
}
|
||||
|
||||
return $self->SUPER::www_add( @_ );
|
||||
return $self->next::method( @_ );
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ package WebGUI::Asset::Wobject::GalleryAlbum;
|
|||
#-------------------------------------------------------------------
|
||||
|
||||
use strict;
|
||||
use base 'WebGUI::Asset::Wobject';
|
||||
use Class::C3;
|
||||
use base qw(WebGUI::AssetAspect::RssFeed WebGUI::Asset::Wobject);
|
||||
use Carp qw( croak );
|
||||
use File::Find;
|
||||
use File::Spec;
|
||||
|
|
@ -77,7 +78,7 @@ sub definition {
|
|||
properties => \%properties,
|
||||
};
|
||||
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
return $class->next::method($session, $definition);
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
|
@ -174,7 +175,7 @@ sub addChild {
|
|||
return undef;
|
||||
}
|
||||
|
||||
return $self->SUPER::addChild( $properties, @_ );
|
||||
return $self->next::method( $properties, @_ );
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
|
@ -400,7 +401,7 @@ sub getCurrentRevisionDate {
|
|||
return $revisionDate;
|
||||
}
|
||||
else {
|
||||
return $class->SUPER::getCurrentRevisionDate( $session, $assetId );
|
||||
return $class->next::method( $session, $assetId );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -497,6 +498,41 @@ sub getPreviousAlbum {
|
|||
return $self->{_previousAlbum};
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getRssFeedItems ()
|
||||
|
||||
Returns an array reference of hash references. Each hash reference has a title,
|
||||
description, link, and date field. The date field can be either an epoch date, an RFC 1123
|
||||
date, or a ISO date in the format of YYYY-MM-DD HH:MM::SS. Optionally specify an
|
||||
author, and a guid field.
|
||||
|
||||
=cut
|
||||
|
||||
sub getRssFeedItems {
|
||||
my $self = shift;
|
||||
|
||||
my $p
|
||||
= $self->getFilePaginator( {
|
||||
perpage => $self->get('itemsPerFeed'),
|
||||
} );
|
||||
|
||||
my $var = [];
|
||||
for my $assetId ( @{ $p->getPageData } ) {
|
||||
my $asset = WebGUI::Asset::Wobject::GalleryAlbum->newPending( $self->session, $assetId );
|
||||
push @{ $var }, {
|
||||
'link' => $asset->getUrl,
|
||||
'guid' => $asset->{_properties}->{ 'assetId' },
|
||||
'title' => $asset->getTitle,
|
||||
'description' => $asset->{_properties}->{ 'description' },
|
||||
'date' => $asset->{_properties}->{ 'creationDate' },
|
||||
'author' => WebGUI::User->new($self->session, $asset->{_properties}->{ 'ownerUserId' })->username
|
||||
};
|
||||
}
|
||||
|
||||
return $var;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getTemplateVars ( )
|
||||
|
|
@ -639,7 +675,7 @@ See WebGUI::Asset::prepareView() for details.
|
|||
|
||||
sub prepareView {
|
||||
my $self = shift;
|
||||
$self->SUPER::prepareView();
|
||||
$self->next::method();
|
||||
|
||||
my $templateId = $self->getParent->get("templateIdViewAlbum");
|
||||
|
||||
|
|
@ -719,7 +755,7 @@ approval workflow.
|
|||
sub processPropertiesFromFormPost {
|
||||
my $self = shift;
|
||||
my $form = $self->session->form;
|
||||
my $errors = $self->SUPER::processPropertiesFromFormPost || [];
|
||||
my $errors = $self->next::method || [];
|
||||
|
||||
# Return if error
|
||||
return $errors if @$errors;
|
||||
|
|
@ -762,7 +798,7 @@ Override update to force isHidden=1 on all albums.
|
|||
sub update {
|
||||
my $self = shift;
|
||||
my $properties = shift;
|
||||
return $self->SUPER::update({ %{ $properties }, isHidden=>1 });
|
||||
return $self->next::method({ %{ $properties }, isHidden=>1 });
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ sub definition {
|
|||
lineage => $i18n->get('sort by asset rank label'),
|
||||
lastUpdated => $i18n->get('sort by last updated label'),
|
||||
},
|
||||
defaultValue =>"score",
|
||||
defaultValue =>"title",
|
||||
hoverHelp =>$i18n->get('default sort description'),
|
||||
label =>$i18n->get('default sort label'),
|
||||
},
|
||||
|
|
@ -238,6 +238,14 @@ sub definition {
|
|||
hoverHelp =>$i18n->get('ratings duration description'),
|
||||
label =>$i18n->get('ratings duration label'),
|
||||
},
|
||||
statisticsCacheTimeout => {
|
||||
tab => "display",
|
||||
fieldType => "interval",
|
||||
defaultValue => 3600,
|
||||
uiLevel => 8,
|
||||
label => $i18n->get("statistics cache timeout label"),
|
||||
hoverHelp => $i18n->get("statistics cache timeout description")
|
||||
},
|
||||
);
|
||||
push(@{$definition}, {
|
||||
assetName=>$i18n->get('assetName'),
|
||||
|
|
@ -520,6 +528,7 @@ sub view {
|
|||
$self->session->style->setScript($self->session->url->extras('wobject/Matrix/matrix.js'), {type =>
|
||||
'text/javascript'});
|
||||
|
||||
my ($varStatistics,$varStatisticsEncoded);
|
||||
my $var = $self->get;
|
||||
$var->{isLoggedIn} = ($self->session->user->userId ne "1");
|
||||
$var->{addMatrixListing_url} = $self->getUrl('func=add;class=WebGUI::Asset::MatrixListing');
|
||||
|
|
@ -527,90 +536,104 @@ sub view {
|
|||
$var->{exportAttributes_url} = $self->getUrl('func=exportAttributes');
|
||||
$var->{listAttributes_url} = $self->getUrl('func=listAttributes');
|
||||
$var->{search_url} = $self->getUrl('func=search');
|
||||
|
||||
# Get the MatrixListing with the most views as an object using getLineage.
|
||||
my ($bestViews_listing) = @{ $self->getLineage(['descendants'], {
|
||||
|
||||
if ($self->canEdit){
|
||||
# Get all the MatrixListings that are still pending.
|
||||
my @pendingListings = @{ $self->getLineage(['descendants'], {
|
||||
includeOnlyClasses => ['WebGUI::Asset::MatrixListing'],
|
||||
orderByClause => "revisionDate asc",
|
||||
returnObjects => 1,
|
||||
statusToInclude => ['pending'],
|
||||
}) };
|
||||
foreach my $pendingListing (@pendingListings){
|
||||
push (@{ $var->{pending_loop} }, {
|
||||
url => $pendingListing->getUrl
|
||||
."?func=view;revision=".$pendingListing->get('revisionDate'),
|
||||
name => $pendingListing->get('title'),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
my $versionTag = WebGUI::VersionTag->getWorking($session, 1);
|
||||
my $noCache =
|
||||
$session->var->isAdminOn
|
||||
|| $self->get("statisticsCacheTimeout") <= 10
|
||||
|| ($versionTag && $versionTag->getId eq $self->get("tagId"));
|
||||
unless ($noCache) {
|
||||
$varStatisticsEncoded = WebGUI::Cache->new($session,"matrixStatistics_".$self->getId)->get;
|
||||
}
|
||||
|
||||
if ($varStatisticsEncoded){
|
||||
$varStatistics = JSON->new->decode($varStatisticsEncoded);
|
||||
}
|
||||
else{
|
||||
# Get the MatrixListing with the most views as an object using getLineage.
|
||||
my ($bestViews_listing) = @{ $self->getLineage(['descendants'], {
|
||||
includeOnlyClasses => ['WebGUI::Asset::MatrixListing'],
|
||||
joinClass => "WebGUI::Asset::MatrixListing",
|
||||
orderByClause => "views desc",
|
||||
limit => 1,
|
||||
returnObjects => 1,
|
||||
}) };
|
||||
if($bestViews_listing){
|
||||
$var->{bestViews_url} = $bestViews_listing->getUrl;
|
||||
$var->{bestViews_count} = $bestViews_listing->get('views');
|
||||
$var->{bestViews_name} = $bestViews_listing->get('title');
|
||||
$var->{bestViews_sortButton} = "<span id='sortByViews'><button type='button'>Sort by views</button></span><br />";
|
||||
}
|
||||
if($bestViews_listing){
|
||||
$varStatistics->{bestViews_url} = $bestViews_listing->getUrl;
|
||||
$varStatistics->{bestViews_count} = $bestViews_listing->get('views');
|
||||
$varStatistics->{bestViews_name} = $bestViews_listing->get('title');
|
||||
$varStatistics->{bestViews_sortButton} = "<span id='sortByViews'><button type='button'>Sort by views</button></span><br />";
|
||||
}
|
||||
|
||||
# Get the MatrixListing with the most compares as an object using getLineage.
|
||||
# Get the MatrixListing with the most compares as an object using getLineage.
|
||||
|
||||
my ($bestCompares_listing) = @{ $self->getLineage(['descendants'], {
|
||||
my ($bestCompares_listing) = @{ $self->getLineage(['descendants'], {
|
||||
includeOnlyClasses => ['WebGUI::Asset::MatrixListing'],
|
||||
joinClass => "WebGUI::Asset::MatrixListing",
|
||||
orderByClause => "compares desc",
|
||||
limit => 1,
|
||||
returnObjects => 1,
|
||||
}) };
|
||||
if($bestCompares_listing){
|
||||
$var->{bestCompares_url} = $bestCompares_listing->getUrl;
|
||||
$var->{bestCompares_count} = $bestCompares_listing->get('compares');
|
||||
$var->{bestCompares_name} = $bestCompares_listing->get('title');
|
||||
$var->{bestCompares_sortButton} = "<span id='sortByCompares'><button type='button'>Sort by compares</button></span><br />";
|
||||
}
|
||||
if($bestCompares_listing){
|
||||
$varStatistics->{bestCompares_url} = $bestCompares_listing->getUrl;
|
||||
$varStatistics->{bestCompares_count} = $bestCompares_listing->get('compares');
|
||||
$varStatistics->{bestCompares_name} = $bestCompares_listing->get('title');
|
||||
$varStatistics->{bestCompares_sortButton} = "<span id='sortByCompares'><button type='button'>Sort by compares</button></span><br />";
|
||||
}
|
||||
|
||||
# Get the MatrixListing with the most clicks as an object using getLineage.
|
||||
my ($bestClicks_listing) = @{ $self->getLineage(['descendants'], {
|
||||
# Get the MatrixListing with the most clicks as an object using getLineage.
|
||||
my ($bestClicks_listing) = @{ $self->getLineage(['descendants'], {
|
||||
includeOnlyClasses => ['WebGUI::Asset::MatrixListing'],
|
||||
joinClass => "WebGUI::Asset::MatrixListing",
|
||||
orderByClause => "clicks desc",
|
||||
limit => 1,
|
||||
returnObjects => 1,
|
||||
}) };
|
||||
if($bestClicks_listing){
|
||||
$var->{bestClicks_url} = $bestClicks_listing->getUrl;
|
||||
$var->{bestClicks_count} = $bestClicks_listing->get('clicks');
|
||||
$var->{bestClicks_name} = $bestClicks_listing->get('title');
|
||||
$var->{bestClicks_sortButton} = "<span id='sortByClicks'><button type='button'>Sort by clicks</button></span><br />";
|
||||
}
|
||||
# Get the 5 MatrixListings that were last updated as objects using getLineage.
|
||||
if($bestClicks_listing){
|
||||
$varStatistics->{bestClicks_url} = $bestClicks_listing->getUrl;
|
||||
$varStatistics->{bestClicks_count} = $bestClicks_listing->get('clicks');
|
||||
$varStatistics->{bestClicks_name} = $bestClicks_listing->get('title');
|
||||
$varStatistics->{bestClicks_sortButton} = "<span id='sortByClicks'><button type='button'>Sort by clicks</button></span><br />";
|
||||
}
|
||||
|
||||
my @lastUpdatedListings = @{ $self->getLineage(['descendants'], {
|
||||
# Get the 5 MatrixListings that were last updated as objects using getLineage.
|
||||
|
||||
my @lastUpdatedListings = @{ $self->getLineage(['descendants'], {
|
||||
includeOnlyClasses => ['WebGUI::Asset::MatrixListing'],
|
||||
joinClass => "WebGUI::Asset::MatrixListing",
|
||||
orderByClause => "lastUpdated desc",
|
||||
limit => 5,
|
||||
returnObjects => 1,
|
||||
}) };
|
||||
foreach my $lastUpdatedListing (@lastUpdatedListings){
|
||||
push (@{ $var->{last_updated_loop} }, {
|
||||
foreach my $lastUpdatedListing (@lastUpdatedListings){
|
||||
push (@{ $varStatistics->{last_updated_loop} }, {
|
||||
url => $lastUpdatedListing->getUrl,
|
||||
name => $lastUpdatedListing->get('title'),
|
||||
lastUpdated => $self->session->datetime->epochToHuman($lastUpdatedListing->get('lastUpdated'),"%z")
|
||||
});
|
||||
}
|
||||
$var->{lastUpdated_sortButton} = "<span id='sortByUpdated'><button type='button'>Sort by updated</button></span><br />";
|
||||
}
|
||||
$var->{lastUpdated_sortButton} = "<span id='sortByUpdated'><button type='button'>Sort by updated</button></span><br />";
|
||||
|
||||
# For each category, get the MatrixListings with the best ratings.
|
||||
|
||||
# Get all the MatrixListings that are still pending.
|
||||
|
||||
my @pendingListings = @{ $self->getLineage(['descendants'], {
|
||||
includeOnlyClasses => ['WebGUI::Asset::MatrixListing'],
|
||||
orderByClause => "revisionDate asc",
|
||||
returnObjects => 1,
|
||||
statusToInclude => ['pending'],
|
||||
}) };
|
||||
foreach my $pendingListing (@pendingListings){
|
||||
push (@{ $var->{pending_loop} }, {
|
||||
url => $pendingListing->getUrl
|
||||
."?func=view;revision=".$pendingListing->get('revisionDate'),
|
||||
name => $pendingListing->get('title'),
|
||||
});
|
||||
}
|
||||
|
||||
# For each category, get the MatrixListings with the best ratings.
|
||||
|
||||
foreach my $category (keys %{$self->getCategories}) {
|
||||
foreach my $category (keys %{$self->getCategories}) {
|
||||
my $data;
|
||||
my $sql = "
|
||||
select
|
||||
|
|
@ -641,7 +664,7 @@ sub view {
|
|||
order by rating.meanValue ";
|
||||
|
||||
$data = $db->quickHashRef($sql." desc limit 1",[$category,$self->getId]);
|
||||
push(@{ $var->{best_rating_loop} },{
|
||||
push(@{ $varStatistics->{best_rating_loop} },{
|
||||
url=>'/'.$data->{url},
|
||||
category=>$category,
|
||||
name=>$data->{productName},
|
||||
|
|
@ -650,7 +673,7 @@ sub view {
|
|||
count=>$data->{countValue}
|
||||
});
|
||||
$data = $db->quickHashRef($sql." asc limit 1",[$category,$self->getId]);
|
||||
push(@{ $var->{worst_rating_loop} },{
|
||||
push(@{ $varStatistics->{worst_rating_loop} },{
|
||||
url=>'/'.$data->{url},
|
||||
category=>$category,
|
||||
name=>$data->{productName},
|
||||
|
|
@ -658,9 +681,9 @@ sub view {
|
|||
median=>$data->{medianValue},
|
||||
count=>$data->{countValue}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$var->{listingCount} = scalar $db->buildArray("
|
||||
$varStatistics->{listingCount} = scalar $db->buildArray("
|
||||
select *
|
||||
from asset, assetData
|
||||
where asset.assetId=assetData.assetId
|
||||
|
|
@ -670,7 +693,17 @@ sub view {
|
|||
and assetData.status='approved'
|
||||
group by asset.assetId",
|
||||
[$self->getId]);
|
||||
|
||||
|
||||
$varStatisticsEncoded = JSON->new->encode($varStatistics);
|
||||
WebGUI::Cache->new($session,"matrixStatistics_".$self->getId)->set(
|
||||
$varStatisticsEncoded,$self->get("statisticsCacheTimeout")
|
||||
);
|
||||
}
|
||||
|
||||
foreach my $statistic (keys %{$varStatistics}) {
|
||||
$var->{$statistic} = $varStatistics->{$statistic};
|
||||
}
|
||||
|
||||
return $self->processTemplate($var, undef, $self->{_viewTemplate});
|
||||
}
|
||||
|
||||
|
|
@ -977,13 +1010,32 @@ sub www_getCompareFormData {
|
|||
my $form = $session->form;
|
||||
my $sort = shift || $session->scratch->get('matrixSort') || $self->get('defaultSort');
|
||||
my $sortDirection = ' desc';
|
||||
# if ( WebGUI::Utility::isIn($sort, qw(revisionDate score)) ) {
|
||||
# $sortDirection = " desc";
|
||||
# }
|
||||
my @results;
|
||||
my @listingIds = $self->session->form->checkList("listingId");
|
||||
if ($sort eq 'title'){
|
||||
$sortDirection = ' asc';
|
||||
}
|
||||
|
||||
$self->session->http->setMimeType("application/json");
|
||||
my @listingIds = $session->form->checkList("listingId");
|
||||
|
||||
$session->http->setMimeType("application/json");
|
||||
|
||||
my (@searchParams,@searchParams_sorted,@searchParamList,$searchParamList);
|
||||
if($form->process("search")){
|
||||
foreach my $param ($form->param) {
|
||||
if($param =~ m/^search_/){
|
||||
my $parameter;
|
||||
$parameter->{name} = $param;
|
||||
$parameter->{value} = $form->process($param);
|
||||
my $attributeId = $param;
|
||||
$attributeId =~ s/^search_//;
|
||||
$attributeId =~ s/_____/-/g;
|
||||
$parameter->{attributeId} = $attributeId;
|
||||
push(@searchParamList,'"'.$parameter->{attributeId}.'"');
|
||||
push(@searchParams,$parameter);
|
||||
}
|
||||
}
|
||||
$searchParamList = join(',',@searchParamList);
|
||||
@searchParams_sorted = sort { $b->{value} <=> $a->{value} } @searchParams;
|
||||
}
|
||||
|
||||
my $sql = "
|
||||
select
|
||||
|
|
@ -1005,31 +1057,17 @@ assetData.revisionDate
|
|||
and assetData.revisionDate = (SELECT max(revisionDate) from assetData where assetId=asset.assetId and status='approved')
|
||||
and status='approved'
|
||||
order by ".$sort.$sortDirection;
|
||||
|
||||
my $sth = $session->db->read($sql,[$self->getId]);
|
||||
my @results;
|
||||
|
||||
@results = @{ $session->db->buildArrayRefOfHashRefs($sql,[$self->getId]) };
|
||||
|
||||
my (@searchParams,@searchParams_sorted);
|
||||
if($form->process("search")){
|
||||
foreach my $param ($form->param) {
|
||||
if($param =~ m/^search_/){
|
||||
my $parameter;
|
||||
$parameter->{name} = $param;
|
||||
$parameter->{value} = $form->process($param);
|
||||
my $attributeId = $param;
|
||||
$attributeId =~ s/^search_//;
|
||||
$attributeId =~ s/_____/-/g;
|
||||
$parameter->{attributeId} = $attributeId;
|
||||
push(@searchParams,$parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@searchParams_sorted = sort { $b->{value} <=> $a->{value} } @searchParams;
|
||||
foreach my $result (@results){
|
||||
if($form->process("search")){
|
||||
while (my $result = $sth->hashRef) {
|
||||
my $matrixListing_attributes = $session->db->buildHashRefOfHashRefs("
|
||||
select value, fieldType, attributeId from Matrix_attribute
|
||||
left join MatrixListing_attribute as listing using(attributeId)
|
||||
where listing.matrixListingId = ? order by value asc",
|
||||
where listing.matrixListingId = ?
|
||||
and attributeId IN(".$searchParamList.")",
|
||||
[$result->{assetId}],'attributeId');
|
||||
PARAM: foreach my $param (@searchParams_sorted) {
|
||||
my $fieldType = $matrixListing_attributes->{$param->{attributeId}}->{fieldType};
|
||||
|
|
@ -1046,20 +1084,27 @@ assetData.revisionDate
|
|||
$result->{checked} = 'checked';
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
$result->{assetId} =~ s/-/_____/g;
|
||||
if(WebGUI::Utility::isIn($result->{assetId},@listingIds)){
|
||||
$result->{checked} = 'checked';
|
||||
}
|
||||
}
|
||||
$result->{assetId} =~ s/-/_____/g;
|
||||
$result->{url} = $session->url->gateway($result->{url});
|
||||
push @results, $result;
|
||||
}
|
||||
}else{
|
||||
while (my $result = $sth->hashRef) {
|
||||
$result->{assetId} =~ s/-/_____/g;
|
||||
if(WebGUI::Utility::isIn($result->{assetId},@listingIds)){
|
||||
$result->{checked} = 'checked';
|
||||
}
|
||||
$result->{url} = $session->url->gateway($result->{url});
|
||||
push @results, $result;
|
||||
}
|
||||
}
|
||||
$sth->finish;
|
||||
|
||||
my $jsonOutput;
|
||||
$jsonOutput->{ResultSet} = {Result=>\@results};
|
||||
|
||||
my $encodedOutput = JSON->new->encode($jsonOutput);
|
||||
|
||||
return $encodedOutput;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -297,8 +297,8 @@ Returns a toolbar with a set of icons that hyperlink to functions that delete, e
|
|||
|
||||
sub getToolbar {
|
||||
my $self = shift;
|
||||
return
|
||||
unless $self->canEdit;
|
||||
return undef
|
||||
unless $self->canEdit && $self->session->var->isAdminOn;
|
||||
if ($self->getToolbarState) {
|
||||
my $toolbar = '';
|
||||
if ($self->canEditIfLocked) {
|
||||
|
|
|
|||
|
|
@ -311,7 +311,7 @@ sub getEditForm {
|
|||
);
|
||||
|
||||
# javascript
|
||||
$self->session->style->setScript("/extras/wobject/SQLReport/editFormDownload.js");
|
||||
$self->session->style->setScript($self->session->url->extras("wobject/SQLReport/editFormDownload.js"), {type => 'text/javascript',});
|
||||
|
||||
### /DOWNLOAD
|
||||
|
||||
|
|
|
|||
|
|
@ -308,10 +308,11 @@ sub view {
|
|||
foreach my $id (@{$p->getPageData}) {
|
||||
my $asset = WebGUI::Asset->newByDynamicClass($session, $id);
|
||||
if (defined $asset) {
|
||||
my $sku = $asset->get;
|
||||
$sku->{url} = $asset->getUrl;
|
||||
$sku->{thumbnailUrl} = $asset->getThumbnailUrl;
|
||||
$sku->{price} = sprintf("%.2f", $asset->getPrice);
|
||||
my $sku = $asset->get;
|
||||
$sku->{url} = $asset->getUrl;
|
||||
$sku->{thumbnailUrl} = $asset->getThumbnailUrl;
|
||||
$sku->{price} = sprintf("%.2f", $asset->getPrice);
|
||||
$sku->{addToCartForm} = $asset->getAddToCartForm;
|
||||
push @skus, $sku;
|
||||
}
|
||||
else {
|
||||
|
|
@ -330,6 +331,13 @@ sub view {
|
|||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_edit ( )
|
||||
|
||||
Override the superclass to add import and exprt items to the AdminConsole submenu.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_edit {
|
||||
my $self = shift;
|
||||
my $i18n = WebGUI::International->new($self->session, 'Asset_Shelf');
|
||||
|
|
|
|||
|
|
@ -112,6 +112,14 @@ sub definition {
|
|||
label => $i18n->get('Max user responses'),
|
||||
hoverHelp => $i18n->get('Max user responses help'),
|
||||
},
|
||||
surveySummaryTemplateId => {
|
||||
tab => 'display',
|
||||
fieldType => 'template',
|
||||
label => $i18n->get('Survey Summary Template'),
|
||||
hoverHelp => $i18n->get('Survey Summary Template help'),
|
||||
defaultValue => '7F-BuEHi7t9bPi008H8xZQ',
|
||||
namespace => 'Survey/Summary',
|
||||
},
|
||||
surveyTakeTemplateId => {
|
||||
tab => 'display',
|
||||
fieldType => 'template',
|
||||
|
|
@ -193,8 +201,19 @@ sub definition {
|
|||
# hoverHelp => $i18n->get('editForm workflowIdAddEntry description'),
|
||||
none => 1,
|
||||
},
|
||||
quizModeSummary => {
|
||||
fieldType => 'yesNo',
|
||||
defaultValue => 0,
|
||||
tab => 'properties',
|
||||
label => $i18n->get('Quiz mode summaries'),
|
||||
hoverHelp => $i18n->get('Quiz mode summaries help'),
|
||||
}
|
||||
);
|
||||
|
||||
#my $defaultMC = $session->
|
||||
|
||||
#%properties = ();
|
||||
|
||||
push @{$definition}, {
|
||||
assetName => $i18n->get('assetName'),
|
||||
icon => 'survey.gif',
|
||||
|
|
@ -412,6 +431,10 @@ sub www_submitObjectEdit {
|
|||
}
|
||||
elsif ( $params->{copy} ) {
|
||||
return $self->copyObject( \@address );
|
||||
}elsif( $params->{removetype} ){
|
||||
return $self->removeType(\@address);
|
||||
}elsif( $params->{addtype} ){
|
||||
return $self->addType($params->{addtype},\@address);
|
||||
}
|
||||
|
||||
# Update the addressed object
|
||||
|
|
@ -493,6 +516,51 @@ sub www_jumpTo {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 removeType ( $address )
|
||||
|
||||
Remove the requested questionType, and then reloads the Survey.
|
||||
|
||||
=head3 $address
|
||||
|
||||
Specifies which questionType to delete.
|
||||
|
||||
=cut
|
||||
|
||||
sub removeType{
|
||||
my $self = shift;
|
||||
my $address = shift;
|
||||
$self->surveyJSON->removeType($address);
|
||||
return $self->www_loadSurvey( { address => $address } );
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 addType ( $name, $address )
|
||||
|
||||
Adds a new questionType, and then reloads the Survey.
|
||||
|
||||
=head3 $name
|
||||
|
||||
The name of the new question type.
|
||||
|
||||
=head3 $address
|
||||
|
||||
Specifies where to add the question.
|
||||
|
||||
=cut
|
||||
|
||||
sub addType{
|
||||
my $self = shift;
|
||||
my $name = shift;
|
||||
my $address = shift;
|
||||
$self->surveyJSON->addType($name,$address);
|
||||
$self->persistSurveyJSON();
|
||||
return $self->www_loadSurvey( { address => $address } );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 copyObject ( )
|
||||
|
||||
Takes the address of a survey object and creates a copy. The copy is placed at the end of this object's parent's list.
|
||||
|
|
@ -705,8 +773,8 @@ sub www_loadSurvey {
|
|||
}
|
||||
|
||||
# Generate the list of valid goto targets
|
||||
my @gotoTargets = $self->surveyJSON->getGotoTargets;
|
||||
|
||||
my $gotoTargets = $self->surveyJSON->getGotoTargets;
|
||||
|
||||
my %buttons;
|
||||
$buttons{question} = $address->[0];
|
||||
if ( @{$address} == 2 or @{$address} == 3 ) {
|
||||
|
|
@ -753,7 +821,9 @@ sub www_loadSurvey {
|
|||
$lastType = 'answer';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
my $warnings = $self->surveyJSON->validateSurvey();
|
||||
|
||||
my $return = {
|
||||
address => $address, # the address of the focused object
|
||||
buttons => \%buttons, # the data to create the Add buttons
|
||||
|
|
@ -761,7 +831,8 @@ sub www_loadSurvey {
|
|||
ddhtml => $html, # the html to create the draggable html divs
|
||||
ids => \@ids, # list of all ids passed in which are draggable (for adding events)
|
||||
type => $var->{type}, # the object type
|
||||
gotoTargets => \@gotoTargets,
|
||||
gotoTargets => $gotoTargets,
|
||||
warnings => $warnings #List of warnings to display to the user
|
||||
};
|
||||
|
||||
$self->session->http->setMimeType('application/json');
|
||||
|
|
@ -883,8 +954,8 @@ sub getResponseInfoForView {
|
|||
|
||||
my ( $code, $taken );
|
||||
|
||||
my $maxTakes = $self->getValue('maxResponsesPerUser');
|
||||
my $id = $self->session->user->userId();
|
||||
my $maxResponsesPerUser = $self->getValue('maxResponsesPerUser');
|
||||
my $userId = $self->session->user->userId();
|
||||
my $anonId
|
||||
= $self->session->form->process('userid')
|
||||
|| $self->session->http->getCookies->{Survey2AnonId}
|
||||
|
|
@ -894,45 +965,45 @@ sub getResponseInfoForView {
|
|||
my $string;
|
||||
|
||||
#if there is an anonid or id is for a WG user
|
||||
if ( $anonId or $id != 1 ) {
|
||||
if ( $anonId or $userId != 1 ) {
|
||||
$string = 'userId';
|
||||
if ($anonId) {
|
||||
$string = 'anonId';
|
||||
$id = $anonId;
|
||||
$userId = $anonId;
|
||||
}
|
||||
my $responseId
|
||||
= $self->session->db->quickScalar(
|
||||
"select Survey_responseId from Survey_response where $string = ? and assetId = ? and isComplete = 0",
|
||||
[ $id, $self->getId() ] );
|
||||
[ $userId, $self->getId() ] );
|
||||
if ( !$responseId ) {
|
||||
$code = $self->session->db->quickScalar(
|
||||
"select isComplete from Survey_response where $string = ? and assetId = ? and isComplete > 0 order by endDate desc limit 1",
|
||||
[ $id, $self->getId() ]
|
||||
[ $userId, $self->getId() ]
|
||||
);
|
||||
}
|
||||
$taken
|
||||
= $self->session->db->quickScalar(
|
||||
"select count(*) from Survey_response where $string = ? and assetId = ? and isComplete > 0",
|
||||
[ $id, $self->getId() ] );
|
||||
[ $userId, $self->getId() ] );
|
||||
|
||||
}
|
||||
elsif ( $id == 1 ) {
|
||||
elsif ( $userId == 1 ) {
|
||||
my $responseId = $self->session->db->quickScalar(
|
||||
'select Survey_responseId from Survey_response where userId = ? and ipAddress = ? and assetId = ? and isComplete = 0',
|
||||
[ $id, $ip, $self->getId() ]
|
||||
[ $userId, $ip, $self->getId() ]
|
||||
);
|
||||
if ( !$responseId ) {
|
||||
$code = $self->session->db->quickScalar(
|
||||
'select isComplete from Survey_response where userId = ? and ipAddress = ? and assetId = ? and isComplete > 0 order by endDate desc limit 1',
|
||||
[ $id, $ip, $self->getId() ]
|
||||
[ $userId, $ip, $self->getId() ]
|
||||
);
|
||||
}
|
||||
$taken = $self->session->db->quickScalar(
|
||||
'select count(*) from Survey_response where userId = ? and ipAddress = ? and assetId = ? and isComplete > 0',
|
||||
[ $id, $ip, $self->getId() ]
|
||||
[ $userId, $ip, $self->getId() ]
|
||||
);
|
||||
}
|
||||
return ( $code, $taken >= $maxTakes );
|
||||
return ( $code, $maxResponsesPerUser > 0 && $taken >= $maxResponsesPerUser );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -1081,6 +1152,14 @@ sub www_submitQuestions {
|
|||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub getSummary{
|
||||
my $self = shift;
|
||||
my $summary = $self->responseJSON->showSummary();
|
||||
my $out = $self->processTemplate( $summary, $self->get('surveySummaryTemplateId') );
|
||||
return $out;
|
||||
# return $self->session->style->process( $out, $self->get('styleTemplateId') );
|
||||
}
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_loadQuestions
|
||||
|
|
@ -1092,7 +1171,7 @@ Determines which questions to display to the survey taker next, loads and return
|
|||
sub www_loadQuestions {
|
||||
my $self = shift;
|
||||
my $wasRestarted = shift;
|
||||
|
||||
|
||||
if ( !$self->canTakeSurvey() ) {
|
||||
$self->session->log->debug('canTakeSurvey false, surveyEnd');
|
||||
return $self->surveyEnd();
|
||||
|
|
@ -1110,6 +1189,12 @@ sub www_loadQuestions {
|
|||
|
||||
if ( $self->responseJSON->surveyEnd() ) {
|
||||
$self->session->log->debug('Response surveyEnd, so calling surveyEnd');
|
||||
if ( $self->get('quizModeSummary') ) {
|
||||
if(! $self->session->form->param('shownsummary')){
|
||||
my $json = to_json( { type => 'summary', summary => $self->getSummary() });
|
||||
return $json;
|
||||
}
|
||||
}
|
||||
return $self->surveyEnd();
|
||||
}
|
||||
|
||||
|
|
@ -1191,7 +1276,7 @@ sub surveyEnd {
|
|||
}
|
||||
}
|
||||
}
|
||||
$url = $self->session->url->gateway($url);
|
||||
$url = $self->session->url->gateway($url) if($url !~ /^http:/i);
|
||||
#$self->session->http->setRedirect($url);
|
||||
#$self->session->http->setMimeType('application/json');
|
||||
my $json = to_json( { type => 'forward', url => $url } );
|
||||
|
|
@ -1208,17 +1293,18 @@ Sends the processed template and questions structure to the client
|
|||
|
||||
sub prepareShowSurveyTemplate {
|
||||
my ( $self, $section, $questions ) = @_;
|
||||
my %multipleChoice = (
|
||||
'Multiple Choice', 1, 'Gender', 1, 'Yes/No', 1, 'True/False', 1, 'Ideology', 1,
|
||||
'Race', 1, 'Party', 1, 'Education', 1, 'Scale', 1, 'Agree/Disagree', 1,
|
||||
'Oppose/Support', 1, 'Importance', 1, 'Likelihood', 1, 'Certainty', 1, 'Satisfaction', 1,
|
||||
'Confidence', 1, 'Effectiveness', 1, 'Concern', 1, 'Risk', 1, 'Threat', 1,
|
||||
'Security', 1
|
||||
);
|
||||
# my %multipleChoice = (
|
||||
# 'Multiple Choice', 1, 'Gender', 1, 'Yes/No', 1, 'True/False', 1, 'Ideology', 1,
|
||||
# 'Race', 1, 'Party', 1, 'Education', 1, 'Scale', 1, 'Agree/Disagree', 1,
|
||||
# 'Oppose/Support', 1, 'Importance', 1, 'Likelihood', 1, 'Certainty', 1, 'Satisfaction', 1,
|
||||
# 'Confidence', 1, 'Effectiveness', 1, 'Concern', 1, 'Risk', 1, 'Threat', 1,
|
||||
# 'Security', 1
|
||||
# );
|
||||
my %textArea = ( 'TextArea', 1 );
|
||||
my %text = ( 'Text', 1, 'Email', 1, 'Phone Number', 1, 'Text Date', 1, 'Currency', 1 );
|
||||
my %slider = ( 'Slider', 1, 'Dual Slider - Range', 1, 'Multi Slider - Allocate', 1 );
|
||||
my %dateType = ( 'Date', 1, 'Date Range', 1 );
|
||||
my %dateShort = ( 'Year Month', 1 );
|
||||
my %fileUpload = ( 'File Upload', 1 );
|
||||
my %hidden = ( 'Hidden', 1 );
|
||||
|
||||
|
|
@ -1227,7 +1313,7 @@ sub prepareShowSurveyTemplate {
|
|||
elsif ( $text{ $q->{questionType} } ) { $q->{textType} = 1; }
|
||||
elsif ( $textArea{ $q->{questionType} } ) { $q->{textAreaType} = 1; }
|
||||
elsif ( $hidden{ $q->{questionType} } ) { $q->{hidden} = 1; }
|
||||
elsif ( $multipleChoice{ $q->{questionType} } ) {
|
||||
elsif ( $self->surveyJSON->multipleChoiceTypes->{ $q->{questionType} } ) {
|
||||
$q->{multipleChoice} = 1;
|
||||
if ( $q->{maxAnswers} > 1 ) {
|
||||
$q->{maxMoreOne} = 1;
|
||||
|
|
@ -1236,6 +1322,26 @@ sub prepareShowSurveyTemplate {
|
|||
elsif ( $dateType{ $q->{questionType} } ) {
|
||||
$q->{dateType} = 1;
|
||||
}
|
||||
elsif ( $dateShort{ $q->{questionType} } ) {
|
||||
$q->{dateShort} = 1;
|
||||
foreach my $a(@{$q->{answers}}){
|
||||
$a->{months} = [
|
||||
{'month' => ''},
|
||||
{'month' => 'January'},
|
||||
{'month' => 'February'},
|
||||
{'month' => 'March'},
|
||||
{'month' => 'April'},
|
||||
{'month' => 'May'},
|
||||
{'month' => 'June'},
|
||||
{'month' => 'July'},
|
||||
{'month' => 'August'},
|
||||
{'month' => 'September'},
|
||||
{'month' => 'October'},
|
||||
{'month' => 'November'},
|
||||
{'month' => 'December'}
|
||||
];
|
||||
}
|
||||
}
|
||||
elsif ( $slider{ $q->{questionType} } ) {
|
||||
$q->{slider} = 1;
|
||||
if ( $q->{questionType} eq 'Dual Slider - Range' ) {
|
||||
|
|
@ -1331,7 +1437,7 @@ sub persistResponseJSON {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 responseId
|
||||
=head2 responseIdCookies
|
||||
|
||||
Mutator for the responseIdCookies that determines whether cookies are used as
|
||||
part of the L<"responseId"> lookup process.
|
||||
|
|
@ -1412,7 +1518,7 @@ sub responseId {
|
|||
}
|
||||
|
||||
if ( !$responseId ) {
|
||||
my $allowedTakes = $self->get('maxResponsesPerUser');
|
||||
my $maxResponsesPerUser = $self->get('maxResponsesPerUser');
|
||||
my $haveTaken;
|
||||
|
||||
if ( $id == 1 ) {
|
||||
|
|
@ -1428,7 +1534,7 @@ sub responseId {
|
|||
[ $id, $self->getId() ] );
|
||||
}
|
||||
|
||||
if ( $haveTaken < $allowedTakes ) {
|
||||
if ( $maxResponsesPerUser == 0 || $haveTaken < $maxResponsesPerUser ) {
|
||||
$responseId = $self->session->db->setRow(
|
||||
'Survey_response',
|
||||
'Survey_responseId', {
|
||||
|
|
@ -1450,7 +1556,7 @@ sub responseId {
|
|||
$self->persistResponseJSON();
|
||||
}
|
||||
else {
|
||||
$self->session->log->debug("haveTaken ($haveTaken) >= allowedTakes ($allowedTakes)");
|
||||
$self->session->log->debug("haveTaken ($haveTaken) >= maxResponsesPerUser ($maxResponsesPerUser)");
|
||||
}
|
||||
}
|
||||
$self->{responseId} = $responseId;
|
||||
|
|
@ -1475,25 +1581,26 @@ sub canTakeSurvey {
|
|||
return 0;
|
||||
}
|
||||
|
||||
my $maxTakes = $self->getValue('maxResponsesPerUser');
|
||||
my $ip = $self->session->env->getIp;
|
||||
my $id = $self->session->user->userId();
|
||||
my $takenCount = 0;
|
||||
my $maxResponsesPerUser = $self->getValue('maxResponsesPerUser');
|
||||
my $ip = $self->session->env->getIp;
|
||||
my $userId = $self->session->user->userId();
|
||||
my $takenCount = 0;
|
||||
|
||||
if ( $id == 1 ) {
|
||||
if ( $userId == 1 ) {
|
||||
$takenCount = $self->session->db->quickScalar(
|
||||
'select count(*) from Survey_response where userId = ? and ipAddress = ? '
|
||||
. 'and assetId = ? and isComplete > ?', [ $id, $ip, $self->getId(), 0 ]
|
||||
. 'and assetId = ? and isComplete > ?', [ $userId, $ip, $self->getId(), 0 ]
|
||||
);
|
||||
}
|
||||
else {
|
||||
$takenCount
|
||||
= $self->session->db->quickScalar(
|
||||
'select count(*) from Survey_response where userId = ? and assetId = ? and isComplete > ?',
|
||||
[ $id, $self->getId(), 0 ] );
|
||||
[ $userId, $self->getId(), 0 ] );
|
||||
}
|
||||
|
||||
if ( $takenCount >= $maxTakes ) {
|
||||
# A maxResponsesPerUser value of 0 implies unlimited
|
||||
if ( $maxResponsesPerUser > 0 && $takenCount >= $maxResponsesPerUser ) {
|
||||
$self->{canTake} = 0;
|
||||
}
|
||||
else {
|
||||
|
|
@ -1642,6 +1749,13 @@ sub www_viewStatisticalOverview {
|
|||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_exportTransposedResults ()
|
||||
|
||||
Exports transposed results in a tab deliniated file.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_exportSimpleResults {
|
||||
my $self = shift;
|
||||
|
||||
|
|
@ -1660,7 +1774,7 @@ sub www_exportSimpleResults {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_exportTransposedResults (){
|
||||
=head2 www_exportTransposedResults ()
|
||||
|
||||
Returns transposed results as a tabbed file.
|
||||
|
||||
|
|
|
|||
217
lib/WebGUI/Asset/Wobject/Survey/ExpressionEngine.pm
Normal file
217
lib/WebGUI/Asset/Wobject/Survey/ExpressionEngine.pm
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
package WebGUI::Asset::Wobject::Survey::ExpressionEngine;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Asset::Wobject::Survey::ExpressionEngine
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This class is used to process Survey gotoExpressions.
|
||||
|
||||
See L<run> for more details.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Params::Validate qw(:all);
|
||||
use Safe;
|
||||
use Data::Dumper;
|
||||
use List::Util qw/sum/;
|
||||
Params::Validate::validation_options( on_fail => sub { WebGUI::Error::InvalidParam->throw( error => shift ) } );
|
||||
|
||||
# We need these as semi-globals so that utility subs (which are shared with the safe compartment)
|
||||
# can access them.
|
||||
my $session;
|
||||
my $values;
|
||||
my $scores;
|
||||
my $jump_count;
|
||||
my $validate;
|
||||
my $validTargets;
|
||||
|
||||
=head2 value
|
||||
|
||||
Utility sub that gives expressions access to recorded response values
|
||||
|
||||
value(question_variable) returns the recorded response value for the answer to question_variable
|
||||
|
||||
=cut
|
||||
|
||||
sub value($) {
|
||||
my $key = shift;
|
||||
my $value = $values->{$key};
|
||||
$session->log->debug("[$key] resolves to [$value]");
|
||||
return $value; # scalar variable, so no need to clone
|
||||
}
|
||||
|
||||
=head2 score
|
||||
|
||||
Utility sub that gives expressions access to recorded response scores.
|
||||
|
||||
score(question_variable) returns the score for the answer selected for question_variable
|
||||
score(section_variable) returns the summed score for the answers to all the questions in section_variable
|
||||
|
||||
=cut
|
||||
|
||||
sub score($) {
|
||||
my $key = shift;
|
||||
my $score = $scores->{$key};
|
||||
$session->log->debug("[$key] resolves to [$score]");
|
||||
return $score; # scalar variable, so no need to clone
|
||||
}
|
||||
|
||||
=head2 jump
|
||||
|
||||
Utility sub shared with Safe compartment so that expressions can call individual jump tests.
|
||||
|
||||
Throws an exception containing the jump target when a jump matches, thus allowing L<run> to
|
||||
catch the first successful jump.
|
||||
|
||||
=cut
|
||||
|
||||
sub jump(&$) {
|
||||
my ( $sub, $target ) = @_;
|
||||
$jump_count++;
|
||||
|
||||
# If $validTargets known, make sure target is valid
|
||||
if ($validTargets && !exists $validTargets->{$target}) {
|
||||
$session->log->debug("Invalid target [$target]");
|
||||
if ($validate) {
|
||||
die("Invalid jump target \"$target\""); # bail and report error
|
||||
} else {
|
||||
return; # skip jump but continue with expression
|
||||
}
|
||||
}
|
||||
|
||||
if ( $sub->() ) {
|
||||
$session->log->debug("jump call #$jump_count is truthy");
|
||||
die( { jump => $target } );
|
||||
}
|
||||
else {
|
||||
$session->log->debug("jump call #$jump_count is falsey");
|
||||
}
|
||||
}
|
||||
|
||||
=head2 avg
|
||||
|
||||
Utility sub shared with Safe compartment to allows expressions to easily compute the average of a list
|
||||
|
||||
=cut
|
||||
|
||||
sub avg {
|
||||
my @vals = @_;
|
||||
return sum(@vals) / @vals;
|
||||
}
|
||||
|
||||
=head2 run ( $session, $expression, $opts )
|
||||
|
||||
Class method.
|
||||
|
||||
Evaluates the given expression in a Safe compartment.
|
||||
|
||||
=head3 session
|
||||
|
||||
A WebGUI::Session
|
||||
|
||||
=head3 expression
|
||||
|
||||
The expression to run.
|
||||
|
||||
A gotoExpression is essentially a perl expression that gets evaluated in a Safe compartment.
|
||||
|
||||
To access Section/Question recorded response values, the expression calls L<value>.
|
||||
To access Section/Question recorded response scores, the expression calls L<score>.
|
||||
To trigger a jump, the expression calls L<jump>. The first truthy jump succeeds.
|
||||
We also give expressions access to some useful utility subs such as avg(), and all of the
|
||||
handy subs from List::Util (min, max, sum, etc..).
|
||||
|
||||
A very simple expression that checks if the response to s1q1 is 0 might look like:
|
||||
|
||||
jump { value(s1q1) == 0 } target
|
||||
|
||||
A more complicated gotoExpression with two possible jumps might look like:
|
||||
|
||||
jump { value(q1) > 5 and value(s2q1) =~ m/textmatch/ } target1;
|
||||
jump { avg(value(q1), value(q2), value(q3)) > 10 } target2;
|
||||
|
||||
=head3 opts (optional)
|
||||
|
||||
Supported options are:
|
||||
|
||||
=over 3
|
||||
|
||||
=item * values
|
||||
|
||||
Hashref of values to make available to the expression via the L<value> utility sub
|
||||
|
||||
=item * scores
|
||||
|
||||
Hashref of scores to make available to the expression via the L<score> utility sub
|
||||
|
||||
=item* validTargets
|
||||
|
||||
A hashref of valid jump targets. If this is provided, all L<jump> calls will fail unless
|
||||
the specified target is a key in the hashref.
|
||||
|
||||
=item * validate
|
||||
|
||||
Return errors rather than just logging them (useful for displaying survey validation errors to users)
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub run {
|
||||
my $class = shift;
|
||||
my ( $s, $expression, $opts )
|
||||
= validate_pos( @_, { isa => 'WebGUI::Session' }, { type => SCALAR }, { type => HASHREF, default => {} } );
|
||||
|
||||
# Init package globals
|
||||
( $session, $values, $scores, $jump_count, $validate, $validTargets ) = ( $s, $opts->{values}, $opts->{scores}, 0, $opts->{validate}, $opts->{validTargets} );
|
||||
|
||||
if (!$session->config->get('enableSurveyExpressionEngine')) {
|
||||
$session->log->debug('enableSurveyExpressionEngine config option disabled, skipping');
|
||||
return;
|
||||
}
|
||||
|
||||
# Create the Safe compartment
|
||||
my $compartment = Safe->new();
|
||||
|
||||
# Share our utility subs with the compartment
|
||||
$compartment->share('&value');
|
||||
$compartment->share('&score');
|
||||
$compartment->share('&jump');
|
||||
$compartment->share('&avg');
|
||||
|
||||
# Give them all of List::Util too
|
||||
$compartment->share_from('List::Util', ['&first', '&max', '&maxstr', '&min', '&minstr', '&reduce', '&shuffle', '&sum',]);
|
||||
|
||||
$session->log->debug("Expression is: \"$expression\"");
|
||||
$compartment->reval($expression);
|
||||
|
||||
# See if we ran the engine just to check for errors
|
||||
if ($opts->{validate}) {
|
||||
if ($@ && ref $@ ne 'HASH') {
|
||||
my $error = $@;
|
||||
$error =~ s/(.*?) at .*/$1/s; # don't reveal too much
|
||||
return $error;
|
||||
}
|
||||
return; # no validation errors
|
||||
}
|
||||
|
||||
# A successful jump triggers a hashref containing the jump target to be thrown
|
||||
if ( ref $@ && ref $@ eq 'HASH' && $@->{jump} ) {
|
||||
my $jump = $@->{jump};
|
||||
$session->log->debug("Returning [$jump]");
|
||||
return $jump;
|
||||
}
|
||||
|
||||
# Log all other errors (for example compile errors from bad expressions)
|
||||
if ($@) {
|
||||
$session->log->error($@);
|
||||
}
|
||||
|
||||
# Return undef on failure
|
||||
return;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
@ -28,7 +28,7 @@ As a whole, this class represents the complete state of a user's response to a S
|
|||
At the heart of this class is a perl hash that can be serialized
|
||||
as JSON to the database to allow for storage and retrieval of the complete state
|
||||
of a survey response.
|
||||
|
||||
|
||||
Survey instances that allow users to record multiple responses will persist multiple
|
||||
instances of this class to the database (one per distinct user response).
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ number of questions answered (L<"questionsAnswered">) and the Survey start time
|
|||
This package is not intended to be used by any other Asset in WebGUI.
|
||||
|
||||
=head2 surveyOrder
|
||||
|
||||
|
||||
This data strucutre is an array (reference) of Survey addresses (see
|
||||
L<WebGUI::Asset::Wobject::Survey::SurveyJSON/Address Parameter>), stored in the order
|
||||
in which items are presented to the user.
|
||||
|
|
@ -70,7 +70,7 @@ is stored in this hash reference.
|
|||
|
||||
Questions keys are constructed by hypenating the relevant L<"sIndex"> and L<"qIndex">.
|
||||
Answer keys are constructed by hypenating the relevant L<"sIndex">, L<"qIndex"> and L<aIndex|"aIndexes">.
|
||||
|
||||
|
||||
Question entries only contain a comment field:
|
||||
{
|
||||
...
|
||||
|
|
@ -79,7 +79,7 @@ Question entries only contain a comment field:
|
|||
}
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
Answers entries contain: value (the recorded value), time and comment fields.
|
||||
|
||||
{
|
||||
|
|
@ -98,6 +98,7 @@ use strict;
|
|||
use JSON;
|
||||
use Params::Validate qw(:all);
|
||||
use List::Util qw(shuffle);
|
||||
use Safe;
|
||||
Params::Validate::validation_options( on_fail => sub { WebGUI::Error::InvalidParam->throw( error => shift ) } );
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -430,9 +431,9 @@ Processes and records submitted survey responses in the L<"responses"> data stru
|
|||
Does terminal handling, and branch processing, and advances the L<"lastResponse"> index
|
||||
if all required questions have been answered.
|
||||
|
||||
=head3 $responses
|
||||
=head3 $submittedResponses
|
||||
|
||||
A hash ref of form param data. Each element should look like:
|
||||
A hash ref of submitted form param data. Each element should look like:
|
||||
|
||||
{
|
||||
"questionId-comment" => "question comment",
|
||||
|
|
@ -459,11 +460,11 @@ gotoExpression in the set of questions wins.
|
|||
|
||||
sub recordResponses {
|
||||
my $self = shift;
|
||||
my ($responses) = validate_pos( @_, { type => HASHREF } );
|
||||
my ($submittedResponses) = validate_pos( @_, { type => HASHREF } );
|
||||
|
||||
# Build a lookup table of non-multiple choice question types
|
||||
my %knownTypes = map {$_ => 1} $self->survey->specialQuestionTypes;
|
||||
|
||||
my %knownTypes = map {$_ => 1} @{$self->survey->specialQuestionTypes};
|
||||
|
||||
# We want to record responses against the "next" response section and questions, since these are
|
||||
# the items that have just been displayed to the user.
|
||||
my $section = $self->nextResponseSection();
|
||||
|
|
@ -517,37 +518,40 @@ sub recordResponses {
|
|||
}
|
||||
|
||||
# Record Question comment
|
||||
$self->responses->{ $question->{id} }->{comment} = $responses->{ $question->{id} . 'comment' };
|
||||
$self->responses->{ $question->{id} }->{comment} = $submittedResponses->{ $question->{id} . 'comment' };
|
||||
|
||||
# Process Answers in Question..
|
||||
for my $answer ( @{ $question->{answers} } ) {
|
||||
|
||||
# Pluck the values out of the responses hash that we want to record..
|
||||
my $answerValue = $responses->{ $answer->{id} };
|
||||
my $answerComment = $responses->{ $answer->{id} . 'comment' };
|
||||
my $submittedAnswerResponse = $submittedResponses->{ $answer->{id} };
|
||||
my $submittedAnswerComment = $submittedResponses->{ $answer->{id} . 'comment' };
|
||||
|
||||
# Proceed if we're satisfied that response is valid..
|
||||
if ( defined $answerValue && $answerValue =~ /\S/ ) {
|
||||
# Proceed if we're satisfied that the submitted answer response is valid..
|
||||
if ( defined $submittedAnswerResponse && $submittedAnswerResponse =~ /\S/ ) {
|
||||
$aAnswered = 1;
|
||||
if ($knownTypes{$question->{questionType}}) {
|
||||
$self->responses->{ $answer->{id} }->{value} = $answerValue;
|
||||
} else {
|
||||
# Unknown type, must be a multi-choice bundle
|
||||
# For Multi-choice, use recordedAnswer instead of answerValue
|
||||
$self->responses->{ $answer->{id} }->{value} = $answer->{recordedAnswer};
|
||||
}
|
||||
$self->responses->{ $answer->{id} }->{time} = time;
|
||||
$self->responses->{ $answer->{id} }->{comment} = $answerComment;
|
||||
|
||||
# Now, decide what to record. For multi-choice questions, use recordedAnswer.
|
||||
# Otherwise, we use the (raw) submitted response (e.g. text input, date input etc..)
|
||||
$self->responses->{ $answer->{id} }->{value}
|
||||
= $knownTypes{ $question->{questionType} }
|
||||
? $submittedAnswerResponse
|
||||
: $answer->{recordedAnswer};
|
||||
|
||||
$self->responses->{ $answer->{id} }->{time} = time;
|
||||
$self->responses->{ $answer->{id} }->{comment} = $submittedAnswerComment;
|
||||
|
||||
# Handle terminal Answers..
|
||||
if ( $answer->{terminal} ) {
|
||||
$terminal = 1;
|
||||
$terminalUrl = $answer->{terminalUrl};
|
||||
}
|
||||
|
||||
# ..and also gotos..
|
||||
elsif ( $answer->{goto} =~ /\w/ ) {
|
||||
$goto = $answer->{goto};
|
||||
}
|
||||
|
||||
# .. and also gotoExpressions..
|
||||
elsif ( $answer->{gotoExpression} =~ /\w/ ) {
|
||||
$gotoExpression = $answer->{gotoExpression};
|
||||
|
|
@ -645,89 +649,26 @@ indicates that we should branch.
|
|||
|
||||
=head3 $gotoExpression
|
||||
|
||||
The gotoExpression.
|
||||
|
||||
A gotoExpression is a string representing a list of expressions (one per line) of the form:
|
||||
target: expression
|
||||
target: expression
|
||||
...
|
||||
|
||||
This subroutine iterates through the list, processing each line and, all things being
|
||||
well, evaluates the expression. The first expression to evaluate to true triggers a
|
||||
call to goto($target).
|
||||
|
||||
The expression is a simple subset of the formula language used in spreadsheet programs
|
||||
such as Excel, OpenOffice, Google Docs etc..
|
||||
|
||||
Here is an example using section variables S1 and S2 as jump targets and question
|
||||
variables Q1-3 in the expression. It jumps to S1 if the user's answer to Q1 has a value
|
||||
of 3, jumps to S2 if Q2 + Q3 < 10, and otherwise doesn't branch at all (the default).
|
||||
S1: Q1 = 3
|
||||
S2: Q2 + Q3 < 10
|
||||
|
||||
Arguments are evaluated as follows:
|
||||
|
||||
Numeric arguments evaluate as numbers
|
||||
|
||||
=over 4
|
||||
|
||||
=item * No support for strings (and hence no string matching)
|
||||
|
||||
=item * Question variable names (e.g. Q1) evaluate to the numeric value associated with
|
||||
user's answer to that question, or undefined if the user has not answered that question
|
||||
|
||||
=back
|
||||
|
||||
Binary comparisons operators: = != < <= >= >
|
||||
|
||||
=over 4
|
||||
|
||||
=item * return boolean values based on perl's equivalent numeric comparison operators
|
||||
|
||||
=back
|
||||
|
||||
Simple math operators: + - * /
|
||||
|
||||
=over 4
|
||||
|
||||
=item * return numeric values
|
||||
|
||||
=back
|
||||
|
||||
Later we may add Boolean operators: AND( x; y; z; ... ), OR( x; y; z; ... ), NOT( x ), with args separated by
|
||||
semicolons (presumably because spreadsheet formulas use commas to indicate cell ranges)
|
||||
|
||||
Later still you may be able to say AVG(section1) or SUM(section3) and have those functions automatically
|
||||
compute their result over the set of all questions in the given section.
|
||||
But for now those things can be done manually using the limited subset defined.
|
||||
The gotoExpression. See L<WebGUI::Asset::Wobject::Survey::ExpressionEngine> for more info.
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
sub processGotoExpression {
|
||||
my $self = shift;
|
||||
my ($expression) = validate_pos(@_, {type => SCALAR});
|
||||
|
||||
my $responses = $self->recordedResponses();
|
||||
|
||||
# Parse gotoExpressions one after the other (first one that's true wins)
|
||||
foreach my $line (split /\n/, $expression) {
|
||||
my $processed = $self->parseGotoExpression($line, $responses);
|
||||
|
||||
next if !$processed;
|
||||
|
||||
# (ab)use perl's eval to evaluate the processed expression
|
||||
my $result = eval "$processed->{expression}"; ## no critic
|
||||
$self->session->log->warn($@) if $@; ## no critic
|
||||
|
||||
if ($result) {
|
||||
$self->session->log->debug("Truthy, goto [$processed->{target}]");
|
||||
$self->processGoto($processed->{target});
|
||||
return $processed;
|
||||
} else {
|
||||
$self->session->log->debug('Falsy, not branching');
|
||||
next;
|
||||
}
|
||||
|
||||
# Prepare the ingredients..
|
||||
my $values = $self->responseValuesByVariableName;
|
||||
my $scores = $self->responseScoresByVariableName;
|
||||
my %validTargets = map { $_ => 1 } @{$self->survey->getGotoTargets};
|
||||
|
||||
use WebGUI::Asset::Wobject::Survey::ExpressionEngine;
|
||||
my $engine = "WebGUI::Asset::Wobject::Survey::ExpressionEngine";
|
||||
if (my $jump = $engine->run($self->session, $expression, { values => $values, scores => $scores, validTargets => \%validTargets} )) {
|
||||
$self->session->log->debug("Hit. Jumping to [$jump]");
|
||||
$self->processGoto($jump);
|
||||
}
|
||||
$self->session->log->debug("No hits, falling through");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -735,111 +676,129 @@ sub processGotoExpression {
|
|||
|
||||
=head2 recordedResponses
|
||||
|
||||
Returns a hash (reference) of question responses. The hash keys are
|
||||
question variable names. The hash values are the corresponding answer
|
||||
values selected by the user.
|
||||
Returns an array or response information in this response's survey order.
|
||||
|
||||
=cut
|
||||
|
||||
sub recordedResponses {
|
||||
sub recordedResponses{
|
||||
my $self = shift;
|
||||
|
||||
my $responses= {
|
||||
# questionName => response answer value
|
||||
};
|
||||
|
||||
# Populate %responses with the user's data..
|
||||
my $responses= [
|
||||
# {answer info hash}
|
||||
];
|
||||
# Populate @$responses with the user's data..
|
||||
for my $address ( @{ $self->surveyOrder } ) {
|
||||
my $question = $self->survey->question( $address );
|
||||
my ($sIndex, $qIndex) = (sIndex($address), qIndex($address));
|
||||
for my $aIndex (aIndexes($address)) {
|
||||
my $question = $self->survey->question([$sIndex,$qIndex]);
|
||||
my $answerId = $self->answerId($sIndex, $qIndex, $aIndex);
|
||||
if ( defined $self->responses->{$answerId} ) {
|
||||
my $answer = $self->survey->answer( [ $sIndex, $qIndex, $aIndex ] );
|
||||
$responses->{$question->{variable}}
|
||||
= $answer->{value} =~ /\w/ ? $answer->{value}
|
||||
: $question->{value}
|
||||
;
|
||||
push(@$responses, {
|
||||
value => $answer->{value} =~ /\w/ ? $answer->{value} : $question->{value},
|
||||
recordedAnswer => $answer->{recordedAnswer},
|
||||
isCorrect => $answer->{isCorrect},
|
||||
answerText => $answer->{text},
|
||||
address => [$sIndex,$qIndex,$aIndex],
|
||||
questionText => $question->{text},
|
||||
questionValue => $question->{value},
|
||||
questionType => $question->{questionType}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $responses;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 parseGotoExpression( ( $expression, $responses)
|
||||
=head2 responseValuesByVariableName
|
||||
|
||||
Parses a single gotoExpression. Returns undef if processing fails, or the following hashref
|
||||
if things work out well:
|
||||
{ target => $target, expression => $expression }
|
||||
Returns a lookup table to question variable names and recorded response values.
|
||||
|
||||
=head3 $expression
|
||||
|
||||
The expression to process
|
||||
|
||||
=head3 $responses
|
||||
|
||||
Hashref that maps questionNames to response values
|
||||
|
||||
=head3 Explanation:
|
||||
|
||||
Uses the following simple strategy:
|
||||
|
||||
First, parse the expression as:
|
||||
target: expression
|
||||
|
||||
Replace each questionName with its response value (from the $responses hashref)
|
||||
|
||||
Massage the expression into valid perl
|
||||
|
||||
Check that only valid tokens remain. This last step ensures that any invalid questionNames in
|
||||
the expression generate an error because our list of valid tokens doesn't include a-z
|
||||
Only questions with a defined variable name set are included. Values come from
|
||||
the L<responses> hash.
|
||||
|
||||
=cut
|
||||
|
||||
sub parseGotoExpression {
|
||||
my $self = shift;
|
||||
my ($expression, $responses) = validate_pos(@_, { type => SCALAR }, { type => HASHREF, default => {} });
|
||||
|
||||
$self->session->log->debug("Parsing gotoExpression: $expression");
|
||||
|
||||
# Valid gotoExpression tokens are..
|
||||
my $tokens = qr{\s|[-0-9=!<>+*/.()]};
|
||||
|
||||
my ( $target, $rest ) = $expression =~ /\s* ([^:]+?) \s* : \s* (.*)/x;
|
||||
|
||||
$self->session->log->debug("Parsed as Target: [$target], Expression: [$rest]");
|
||||
|
||||
if ( !defined $target ) {
|
||||
$self->session->log->warn('Target undefined');
|
||||
return;
|
||||
sub responseValuesByVariableName {
|
||||
my $self = shift;
|
||||
|
||||
my %lookup;
|
||||
while (my ($address, $response) = each %{$self->responses}) {
|
||||
next if (!$response || !$address);
|
||||
|
||||
# Turn responses s-q-a string into an address array
|
||||
my @address = split /-/, $address;
|
||||
|
||||
# Filter out the non-answer entries
|
||||
next unless @address == 3;
|
||||
|
||||
# Grab the corresponding question
|
||||
my $question = $self->survey->question([@address]);
|
||||
|
||||
# Filter out questions without defined variable names
|
||||
next if !$question || !defined $question->{variable};
|
||||
|
||||
# Add variable => value to our hash
|
||||
$lookup{$question->{variable}} = $response->{value};
|
||||
}
|
||||
return \%lookup;
|
||||
}
|
||||
|
||||
if ( !defined $rest || $rest eq q{} ) {
|
||||
$self->session->log->warn('Expression undefined');
|
||||
return;
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 responseScoresByVariableName
|
||||
|
||||
Returns a lookup table to question variable names and recorded response values.
|
||||
|
||||
Only questions with a defined variable name set are included. Scores come from
|
||||
the L<responses> hash.
|
||||
|
||||
=cut
|
||||
|
||||
sub responseScoresByVariableName {
|
||||
my $self = shift;
|
||||
|
||||
my %lookup;
|
||||
while (my ($address, $response) = each %{$self->responses}) {
|
||||
next if (!$response || !$address);
|
||||
|
||||
# Turn responses s-q-a string into an address array
|
||||
my @address = split /-/, $address;
|
||||
|
||||
# Filter out the non-answer entries
|
||||
next unless @address == 3;
|
||||
|
||||
# Grab the corresponding question
|
||||
my $question = $self->survey->question([@address]);
|
||||
|
||||
# Filter out questions without defined variable names
|
||||
next if !$question || !defined $question->{variable};
|
||||
|
||||
# Grab the corresponding answer
|
||||
my $answer = $self->survey->answer([@address]);
|
||||
|
||||
# Add variable => score to our hash
|
||||
$lookup{$question->{variable}} = $answer->{value};
|
||||
}
|
||||
|
||||
# Replace each questionName with its response value
|
||||
while ( my ( $questionName, $response ) = each %{$responses} ) {
|
||||
$rest =~ s/$questionName/$response/g;
|
||||
|
||||
# Add section score totals
|
||||
for my $s (@{$self->survey->sections}) {
|
||||
next unless $s->{variable};
|
||||
|
||||
my $score = 0;
|
||||
for my $q (@{$s->{questions}}) {
|
||||
next unless $q->{variable};
|
||||
next unless exists $lookup{$q->{variable}};
|
||||
|
||||
$lookup{$s->{variable}} += $lookup{$q->{variable}};
|
||||
}
|
||||
}
|
||||
|
||||
# convert '=' to '==' but don't touch '!=', '<=' or '>='
|
||||
$rest =~ s/(?<![!<>])=(?!=)/==/g;
|
||||
|
||||
if ( $rest !~ /^$tokens+$/ ) {
|
||||
$self->session->log->warn("Contains invalid tokens: $rest");
|
||||
return;
|
||||
}
|
||||
|
||||
$self->session->log->debug("Processed as: $rest");
|
||||
|
||||
return {
|
||||
target => $target,
|
||||
expression => $rest,
|
||||
};
|
||||
|
||||
return \%lookup;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -915,11 +874,12 @@ sub nextQuestions {
|
|||
my $section = $self->nextResponseSection();
|
||||
my $sectionIndex = $self->nextResponseSectionIndex;
|
||||
my $questionsPerPage = $self->survey->section( [ $self->nextResponseSectionIndex ] )->{questionsPerPage};
|
||||
|
||||
# Get all of the existing question responses (so that we can do Section and Question [[var]] replacements
|
||||
my $recordedResponses = $self->recordedResponses();
|
||||
my $responseValuesByVariableName = $self->responseValuesByVariableName();
|
||||
|
||||
# Do text replacement
|
||||
$section->{text} = $self->getTemplatedText($section->{text}, $recordedResponses);
|
||||
$section->{text} = $self->getTemplatedText($section->{text}, $responseValuesByVariableName);
|
||||
|
||||
# Collect all the questions to be shown on the next page..
|
||||
my @questions;
|
||||
|
|
@ -942,7 +902,7 @@ sub nextQuestions {
|
|||
my %questionCopy = %{$self->survey->question( $address )};
|
||||
|
||||
# Do text replacement
|
||||
$questionCopy{text} = $self->getTemplatedText($questionCopy{text}, $recordedResponses);
|
||||
$questionCopy{text} = $self->getTemplatedText($questionCopy{text}, $responseValuesByVariableName);
|
||||
|
||||
# Add any extra fields we want..
|
||||
$questionCopy{id} = $self->questionId($sIndex, $qIndex);
|
||||
|
|
@ -954,7 +914,7 @@ sub nextQuestions {
|
|||
my %answerCopy = %{ $self->survey->answer( [ $sIndex, $qIndex, $aIndex ] ) };
|
||||
|
||||
# Do text replacement
|
||||
$answerCopy{text} = $self->getTemplatedText($answerCopy{text}, $recordedResponses);
|
||||
$answerCopy{text} = $self->getTemplatedText($answerCopy{text}, $responseValuesByVariableName);
|
||||
|
||||
# Add any extra fields we want..
|
||||
$answerCopy{id} = $self->answerId($sIndex, $qIndex, $aIndex);
|
||||
|
|
@ -1086,7 +1046,116 @@ sub aIndexes {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 returnResponsesForReporting
|
||||
=head2 showSummary ( [$sectionAddresses] )
|
||||
|
||||
showSummary returns the current responses summary for the entire response, if
|
||||
no address is passed in, or just the sections addressed by $sectionAddresses.
|
||||
|
||||
For each section, the total correct, wrong, time taken, and points are returned. And each
|
||||
question is listed with the text, given score, user response, and if it was correct.
|
||||
This list is meant for a template and only what is needed should be shown.
|
||||
|
||||
A summary of the entire suvey,
|
||||
|
||||
=cut
|
||||
|
||||
sub showSummary{
|
||||
my $self = shift;
|
||||
my $sectionAddies = shift;#array of section addresses
|
||||
|
||||
my $all = 0;
|
||||
$all = 1 if(! $sectionAddies);
|
||||
|
||||
my ($summaries);
|
||||
|
||||
my $responses = $self->recordedResponses();
|
||||
my %goodSection;
|
||||
map{$goodSection{$_} = 1} @$sectionAddies;
|
||||
|
||||
return if(! $responses);
|
||||
|
||||
my ($sectionIndex, $questionIndex, $answerIndex) = (-1, -1, -1);
|
||||
my ($currentSection,$currentQuestion) = (-1, -1);
|
||||
|
||||
($summaries->{totalCorrect},$summaries->{totalIncorrect}) = (0,0);
|
||||
|
||||
for my $response (@$responses){
|
||||
if(! $all and ! $goodSection{$response->{address}->[0]}){next;}
|
||||
if($response->{isCorrect}){
|
||||
$summaries->{totalCorrect}++;
|
||||
}else{
|
||||
$summaries->{totalIncorrect}++;
|
||||
}
|
||||
$summaries->{totalAnswers}++;
|
||||
if($currentSection != $response->{address}->[0]){
|
||||
$summaries->{totalSections}++;
|
||||
$sectionIndex++;
|
||||
$questionIndex = -1;
|
||||
$answerIndex = -1;
|
||||
$currentQuestion = -1;
|
||||
$currentSection = $response->{address}->[0];
|
||||
_loadSectionIntoSummary(\%{$summaries->{sections}->[$sectionIndex]},$response);
|
||||
}
|
||||
if($currentQuestion != $response->{address}->[1]){
|
||||
$summaries->{totalQuestions}++;
|
||||
$questionIndex++;
|
||||
$answerIndex = -1;
|
||||
$currentQuestion = $response->{address}->[1];
|
||||
_loadQuestionIntoSummary(\%{$summaries->{sections}->[$sectionIndex]->{questions}->[$questionIndex]},$response);
|
||||
}
|
||||
$answerIndex++;
|
||||
_loadAnswerIntoSummary(\%{$summaries->{sections}->[$sectionIndex]->{questions}->[$questionIndex]->{answers}->[$answerIndex]},
|
||||
$response,
|
||||
$self->survey->{multipleChoiceTypes});
|
||||
}
|
||||
return $summaries;
|
||||
}
|
||||
sub _loadAnswerIntoSummary{
|
||||
my $node = shift;
|
||||
my $response = shift;
|
||||
my $types = shift;
|
||||
|
||||
$node->{id} = $response->{address}->[2] + 1;
|
||||
if($response->{isCorrect}){
|
||||
$node->{iscorrect} = 1;
|
||||
$node->{score} = $response->{value};
|
||||
}else{
|
||||
$node->{iscorrect} = 0;
|
||||
$node->{score} = 0;
|
||||
}
|
||||
$node->{text} = $response->{answerText};
|
||||
|
||||
#test if it is a multiple choide type
|
||||
if($types->{$response->{questionType}}){
|
||||
$node->{value} = $response->{value};
|
||||
}else{
|
||||
$node->{value} = $response->{recordedValue};
|
||||
}
|
||||
}
|
||||
sub _loadQuestionIntoSummary{
|
||||
my $node = shift;
|
||||
my $response = shift;
|
||||
$node->{id} = $response->{address}->[1] + 1;
|
||||
$node->{text} = $response->{questionText};
|
||||
}
|
||||
sub _loadSectionIntoSummary{
|
||||
my $node = shift;
|
||||
my $response = shift;
|
||||
$node->{id} = $response->{address}->[0] + 1;
|
||||
$node->{inCorrect} = 0 if(!defined $node->{section}->{inCorrect});
|
||||
$node->{score} = 0 if(!defined $node->{section}->{score});
|
||||
$node->{correct} = 0 if(!defined $node->{section}->{correct});
|
||||
if($response->{isCorrect}){
|
||||
$node->{score} += $response->{value};
|
||||
$node->{correct}++;
|
||||
}else{
|
||||
$node->{inCorrect}++;
|
||||
}
|
||||
|
||||
}
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 returnResponseForReporting
|
||||
|
||||
Used to extract JSON responses for use in reporting results.
|
||||
|
||||
|
|
@ -1096,7 +1165,7 @@ recorded value, and the id of the answer.
|
|||
|
||||
=cut
|
||||
|
||||
# TODO: This sub should make use of recordedResponses
|
||||
# TODO: This sub should make use of responseValuesByVariableName
|
||||
|
||||
sub returnResponseForReporting {
|
||||
my $self = shift;
|
||||
|
|
|
|||
|
|
@ -48,79 +48,18 @@ likely operate on the question indexed by:
|
|||
|
||||
use strict;
|
||||
use JSON;
|
||||
use Data::Dumper;
|
||||
use Params::Validate qw(:all);
|
||||
Params::Validate::validation_options( on_fail => sub { WebGUI::Error::InvalidParam->throw( error => shift ) } );
|
||||
|
||||
# N.B. We're currently using Storable::dclone instead of Clone::clone
|
||||
# because Colin uncovered some Clone bugs in Perl 5.10
|
||||
#use Clone qw/clone/;
|
||||
use Storable qw/dclone/;
|
||||
use Clone qw/clone/;
|
||||
|
||||
# The maximum value of questionsPerPage is currently hardcoded here
|
||||
my $MAX_QUESTIONS_PER_PAGE = 20;
|
||||
|
||||
my %MULTI_CHOICE_BUNDLES = (
|
||||
'Agree/Disagree' => [ 'Strongly disagree', (q{}) x 5, 'Strongly agree' ],
|
||||
Certainty => [ 'Not at all certain', (q{}) x 9, 'Extremely certain' ],
|
||||
Concern => [ 'Not at all concerned', (q{}) x 9, 'Extremely concerned' ],
|
||||
Confidence => [ 'Not at all confident', (q{}) x 9, 'Extremely confident' ],
|
||||
Education => [
|
||||
'Elementary or some high school',
|
||||
'High school/GED',
|
||||
'Some college/vocational school',
|
||||
'College graduate',
|
||||
'Some graduate work',
|
||||
'Master\'s degree',
|
||||
'Doctorate (of any type)',
|
||||
'Other degree (verbatim)',
|
||||
],
|
||||
Effectiveness => [ 'Not at all effective', (q{}) x 9, 'Extremely effective' ],
|
||||
Gender => [qw( Male Female )],
|
||||
Ideology => [
|
||||
'Strongly liberal',
|
||||
'Liberal',
|
||||
'Somewhat liberal',
|
||||
'Middle of the road',
|
||||
'Slightly conservative',
|
||||
'Conservative',
|
||||
'Strongly conservative'
|
||||
],
|
||||
Importance => [ 'Not at all important', (q{}) x 9, 'Extremely important' ],
|
||||
Likelihood => [ 'Not at all likely', (q{}) x 9, 'Extremely likely' ],
|
||||
'Oppose/Support' => [ 'Strongly oppose', (q{}) x 5, 'Strongly support' ],
|
||||
Party =>
|
||||
[ 'Democratic party', 'Republican party (or GOP)', 'Independent party', 'Other party (verbatim)' ],
|
||||
Race =>
|
||||
[ 'American Indian', 'Asian', 'Black', 'Hispanic', 'White non-Hispanic', 'Something else (verbatim)' ],
|
||||
Risk => [ 'No risk', (q{}) x 9, 'Extreme risk' ],
|
||||
Satisfaction => [ 'Not at all satisfied', (q{}) x 9, 'Extremely satisfied' ],
|
||||
Security => [ 'Not at all secure', (q{}) x 9, 'Extremely secure' ],
|
||||
Threat => [ 'No threat', (q{}) x 9, 'Extreme threat' ],
|
||||
'True/False' => [qw( True False )],
|
||||
'Yes/No' => [qw( Yes No )],
|
||||
Scale => [q{}],
|
||||
'Multiple Choice' => [q{}],
|
||||
);
|
||||
|
||||
my @SPECIAL_QUESTION_TYPES = (
|
||||
'Dual Slider - Range',
|
||||
'Multi Slider - Allocate',
|
||||
'Slider',
|
||||
'Currency',
|
||||
'Email',
|
||||
'Phone Number',
|
||||
'Text',
|
||||
'Text Date',
|
||||
'TextArea',
|
||||
'File Upload',
|
||||
'Date',
|
||||
'Date Range',
|
||||
'Hidden',
|
||||
);
|
||||
|
||||
sub specialQuestionTypes {
|
||||
return @SPECIAL_QUESTION_TYPES;
|
||||
}
|
||||
#sub specialQuestionTypes {
|
||||
# return @SPECIAL_QUESTION_TYPES;
|
||||
#}
|
||||
|
||||
=head2 new ( $session, json )
|
||||
|
||||
|
|
@ -153,6 +92,9 @@ sub new {
|
|||
|
||||
bless $self, $class;
|
||||
|
||||
#Load question types
|
||||
$self->loadTypes();
|
||||
|
||||
# Initialise the survey data structure if empty..
|
||||
if ( $self->totalSections == 0 ) {
|
||||
$self->newObject( [] );
|
||||
|
|
@ -160,6 +102,78 @@ sub new {
|
|||
return $self;
|
||||
}
|
||||
|
||||
=head2 loadTypes
|
||||
|
||||
Loads the Multiple Choice and Special Question types
|
||||
|
||||
=cut
|
||||
|
||||
sub loadTypes {
|
||||
my $self = shift;
|
||||
@{$self->{specialQuestionTypes}} = (
|
||||
'Dual Slider - Range',
|
||||
'Multi Slider - Allocate',
|
||||
'Slider',
|
||||
'Currency',
|
||||
'Email',
|
||||
'Phone Number',
|
||||
'Text',
|
||||
'Text Date',
|
||||
'TextArea',
|
||||
'File Upload',
|
||||
'Date',
|
||||
'Date Range',
|
||||
'Year Month',
|
||||
'Hidden',
|
||||
);
|
||||
my $refs = $self->session->db->buildArrayRefOfHashRefs("SELECT questionType, answers FROM Survey_questionTypes");
|
||||
map($self->{multipleChoiceTypes}->{$_->{questionType}} = [split/,/,$_->{answers}], @$refs);
|
||||
}
|
||||
|
||||
sub addType {
|
||||
my $self = shift;
|
||||
my $name = shift;
|
||||
my $address = shift;
|
||||
my $obj = $self->getObject($address);
|
||||
my @answers;
|
||||
for my $ans(@{$obj->{answers}}){
|
||||
push(@answers,$ans->{text});
|
||||
}
|
||||
my $ansString = join(',',@answers);
|
||||
$self->session->db->write("INSERT INTO Survey_questionTypes VALUES(?,?) ON DUPLICATE KEY UPDATE answers = ?",[$name,$ansString,$ansString]);
|
||||
$self->question($address)->{questionType} = $name;
|
||||
}
|
||||
|
||||
|
||||
sub removeType {
|
||||
my $self = shift;
|
||||
my $address = shift;
|
||||
my $obj = $self->getObject($address);
|
||||
$self->session->db->write("DELETE FROM Survey_questionTypes WHERE questionType = ?",[$obj->{questionType}]);
|
||||
}
|
||||
|
||||
=head2 specialQuestionTypes
|
||||
|
||||
Returns the arrayref to the special question types
|
||||
|
||||
=cut
|
||||
|
||||
sub specialQuestionTypes {
|
||||
my $self = shift;
|
||||
return $self->{specialQuestionTypes};
|
||||
}
|
||||
|
||||
=head2 multipleChoiceTypes
|
||||
|
||||
Returns the hashref to the multiple choice types
|
||||
|
||||
=cut
|
||||
|
||||
sub multipleChoiceTypes {
|
||||
my $self = shift;
|
||||
return $self->{multipleChoiceTypes};
|
||||
}
|
||||
|
||||
=head2 freeze
|
||||
|
||||
Serialize this Perl object into a JSON string. The serialized object is made up of the survey and sections
|
||||
|
|
@ -350,13 +364,13 @@ sub getObject {
|
|||
return if !$count;
|
||||
|
||||
if ( $count == 1 ) {
|
||||
return dclone $self->sections->[ sIndex($address) ];
|
||||
return clone $self->sections->[ sIndex($address) ];
|
||||
}
|
||||
elsif ( $count == 2 ) {
|
||||
return dclone $self->sections->[ sIndex($address) ]->{questions}->[ qIndex($address) ];
|
||||
return clone $self->sections->[ sIndex($address) ]->{questions}->[ qIndex($address) ];
|
||||
}
|
||||
else {
|
||||
return dclone $self->sections->[ sIndex($address) ]->{questions}->[ qIndex($address) ]->{answers}
|
||||
return clone $self->sections->[ sIndex($address) ]->{questions}->[ qIndex($address) ]->{answers}
|
||||
->[ aIndex($address) ];
|
||||
}
|
||||
}
|
||||
|
|
@ -403,12 +417,14 @@ sub getGotoTargets {
|
|||
|
||||
# Valid goto targets are all of the section variable names..
|
||||
my @section_vars = map {$_->{variable}} @{$self->sections};
|
||||
|
||||
|
||||
# ..and all of the question variable names..
|
||||
my @question_vars = map {$_->{variable}} @{$self->questions};
|
||||
|
||||
|
||||
# ..excluding the ones that are empty
|
||||
return grep { $_ ne q{} } (@section_vars, @question_vars);
|
||||
my @grep = grep { $_ ne q{} } (@section_vars, @question_vars);
|
||||
return \@grep;
|
||||
#return grep { $_ ne q{} } (@section_vars, @question_vars);
|
||||
}
|
||||
|
||||
=head2 getSectionEditVars ( $address )
|
||||
|
|
@ -512,7 +528,6 @@ sub getQuestionEditVars {
|
|||
|
||||
# Change questionType from a single element into an array of hashrefs which list the available
|
||||
# question types and which one is currently selected for this question..
|
||||
|
||||
for my $qType ($self->getValidQuestionTypes) {
|
||||
push @{ $var{questionType} }, {
|
||||
text => $qType,
|
||||
|
|
@ -529,7 +544,8 @@ A convenience method. Returns a list of question types.
|
|||
=cut
|
||||
|
||||
sub getValidQuestionTypes {
|
||||
return sort (@SPECIAL_QUESTION_TYPES, keys %MULTI_CHOICE_BUNDLES);
|
||||
my $self = shift;
|
||||
return sort (@{$self->{specialQuestionTypes}}, keys %{$self->{multipleChoiceTypes}});
|
||||
}
|
||||
|
||||
=head2 getAnswerEditVars ( $address )
|
||||
|
|
@ -761,14 +777,14 @@ sub copy {
|
|||
|
||||
if ( $count == 1 ) {
|
||||
# Clone the indexed section onto the end of the list of sections..
|
||||
push @{ $self->sections }, dclone $self->section($address);
|
||||
push @{ $self->sections }, clone $self->section($address);
|
||||
|
||||
# Update $address with the index of the newly created section
|
||||
$address->[0] = $self->lastSectionIndex;
|
||||
}
|
||||
elsif ( $count == 2 ) {
|
||||
# Clone the indexed question onto the end of the list of questions..
|
||||
push @{ $self->questions($address) }, dclone $self->question($address);
|
||||
push @{ $self->questions($address) }, clone $self->question($address);
|
||||
|
||||
# Update $address with the index of the newly created question
|
||||
$address->[1] = $self->lastQuestionIndex($address);
|
||||
|
|
@ -1002,7 +1018,7 @@ sub getMultiChoiceBundle {
|
|||
my $self = shift;
|
||||
my ($type) = validate_pos( @_, { type => SCALAR | UNDEF } );
|
||||
|
||||
return $MULTI_CHOICE_BUNDLES{$type};
|
||||
return $self->{multipleChoiceTypes}->{$type};
|
||||
}
|
||||
|
||||
=head2 addAnswersToQuestion ($address, $answers, $verbatims)
|
||||
|
|
@ -1047,7 +1063,7 @@ sub addAnswersToQuestion {
|
|||
$self->update(
|
||||
\@address_copy,
|
||||
{ text => $answers->[$answer_index],
|
||||
recordedAnswer => $answer_index + 1,
|
||||
recordedAnswer => $answer_index + 1, # 1-indexed
|
||||
verbatim => $verbatims->{$answer_index},
|
||||
}
|
||||
);
|
||||
|
|
@ -1176,6 +1192,123 @@ sub totalAnswers {
|
|||
}
|
||||
}
|
||||
|
||||
=head2 validateSurvey ()
|
||||
|
||||
Returns an array of messages to inform a user what is logically wrong with the Survey
|
||||
|
||||
=cut
|
||||
|
||||
sub validateSurvey{
|
||||
my $self = shift;
|
||||
#check all goto's
|
||||
#bad goto expressions
|
||||
#check that all survey is able to be seen
|
||||
|
||||
my @messages;
|
||||
|
||||
#set up valid goto targets
|
||||
my $gotoTargets = $self->getGotoTargets();
|
||||
my $goodTargets;
|
||||
my $duplicateTargets;
|
||||
for my $g (@{$gotoTargets}) {
|
||||
$goodTargets->{$g}++;
|
||||
$duplicateTargets->{$g}++ if $goodTargets->{$g} > 1;
|
||||
}
|
||||
|
||||
#step through each section validating it.
|
||||
my $sections = $self->sections();
|
||||
|
||||
for(my $s = 0; $s <= $#$sections; $s++){
|
||||
my $sNum = $s + 1;
|
||||
my $section = $self->section([$s]);
|
||||
if(! $self->validateGoto($section,$goodTargets)){
|
||||
push @messages,"Section $sNum has invalid Jump target: \"$section->{goto}\"";
|
||||
}
|
||||
if(! $self->validateGotoInfiniteLoop($section)){
|
||||
push @messages,"Section $sNum jumps to itself.";
|
||||
}
|
||||
if(my $error = $self->validateGotoExpression($section,$goodTargets)){
|
||||
push @messages,"Section $sNum has invalid Jump Expression: \"$section->{gotoExpression}\". Error: $error";
|
||||
}
|
||||
if (my $var = $section->{variable}) {
|
||||
if (my $count = $duplicateTargets->{$var}) {
|
||||
push @messages, "Section $sNum variable name $var is re-used in $count other place(s).";
|
||||
}
|
||||
}
|
||||
|
||||
#step through each question validating it.
|
||||
my $questions = $self->questions([$s]);
|
||||
for(my $q = 0; $q <= $#$questions; $q++){
|
||||
my $qNum = $q + 1;
|
||||
my $question = $self->question([$s,$q]);
|
||||
if(! $self->validateGoto($question,$goodTargets)){
|
||||
push @messages,"Section $sNum Question $qNum has invalid Jump target: \"$question->{goto}\"";
|
||||
}
|
||||
if(! $self->validateGotoInfiniteLoop($question)){
|
||||
push @messages,"Section $sNum Question $qNum jumps to itself.";
|
||||
}
|
||||
if(my $error = $self->validateGotoExpression($question,$goodTargets)){
|
||||
push @messages,"Section $sNum Question $qNum has invalid Jump Expression: \"$question->{gotoExpression}\". Error: $error";
|
||||
}
|
||||
if($#{$question->{answers}} < 0){
|
||||
push @messages,"Section $sNum Question $qNum does not have any answers.";
|
||||
}
|
||||
if(! $question->{text} =~ /\w/){
|
||||
push @messages,"Section $sNum Question $qNum does not have any text.";
|
||||
}
|
||||
if (my $var = $question->{variable}) {
|
||||
if (my $count = $duplicateTargets->{$var}) {
|
||||
push @messages, "Section $sNum Question $qNum variable name $var is re-used in $count other place(s).";
|
||||
}
|
||||
}
|
||||
|
||||
#step through each answer validating it.
|
||||
my $answers = $self->answers([$s,$q]);
|
||||
for(my $a = 0; $a <= $#$answers; $a++){
|
||||
my $aNum = $a + 1;
|
||||
my $answer = $self->answer([$s,$q,$a]);
|
||||
if(! $self->validateGoto($answer,$goodTargets)){
|
||||
push @messages,"Section $sNum Question $qNum Answer $aNum has invalid Jump target: \"$answer->{goto}\"";
|
||||
}
|
||||
if(! $self->validateGotoInfiniteLoop($answer)){
|
||||
push @messages,"Section $sNum Question $qNum Answer $aNum jumps to itself.";
|
||||
}
|
||||
if(my $error = $self->validateGotoExpression($answer,$goodTargets)){
|
||||
push @messages,"Section $sNum Question $qNum Answer $aNum has invalid Jump Expression: \"$answer->{gotoExpression}\". Error: $error";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return \@messages;
|
||||
}
|
||||
|
||||
sub validateGoto{
|
||||
my $self = shift;
|
||||
my $object = shift;
|
||||
my $goodTargets = shift;
|
||||
return 0 if($object->{goto} =~ /\w/ && ! exists($goodTargets->{$object->{goto}}));
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub validateGotoInfiniteLoop{
|
||||
my $self = shift;
|
||||
my $object = shift;
|
||||
return 0 if($object->{goto} =~ /\w/ and $object->{goto} eq $object->{variable});
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub validateGotoExpression{
|
||||
my $self = shift;
|
||||
my $object = shift;
|
||||
my $goodTargets = shift;
|
||||
return unless $object->{gotoExpression};
|
||||
|
||||
use WebGUI::Asset::Wobject::Survey::ExpressionEngine;
|
||||
my $engine = "WebGUI::Asset::Wobject::Survey::ExpressionEngine";
|
||||
return $engine->run($self->session, $object->{gotoExpression}, { validate => 1, validTargets => $goodTargets } );
|
||||
}
|
||||
|
||||
=head2 section ($address)
|
||||
|
||||
Returns a reference to one section.
|
||||
|
|
@ -1208,9 +1341,9 @@ sub session {
|
|||
|
||||
Returns a reference to all the questions from a particular section.
|
||||
|
||||
=head3 $address
|
||||
=head3 $address (optional)
|
||||
|
||||
See L<"Address Parameter">.
|
||||
See L<"Address Parameter">. If not defined, returns all questions.
|
||||
|
||||
=cut
|
||||
|
||||
|
|
@ -1218,7 +1351,13 @@ sub questions {
|
|||
my $self = shift;
|
||||
my ($address) = validate_pos(@_, { type => ARRAYREF, optional => 1});
|
||||
|
||||
return $self->sections->[ $address->[0] ]->{questions};
|
||||
if ($address) {
|
||||
return $self->sections->[ $address->[0] ]->{questions};
|
||||
} else {
|
||||
my $questions;
|
||||
push @$questions, @{$_->{questions} || []} for @{$self->sections};
|
||||
return $questions;
|
||||
}
|
||||
}
|
||||
|
||||
=head2 question ($address)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ use WebGUI::Cache;
|
|||
use WebGUI::Exception;
|
||||
use WebGUI::HTML;
|
||||
use WebGUI::International;
|
||||
use base 'WebGUI::Asset::Wobject';
|
||||
use Class::C3;
|
||||
use base qw(WebGUI::AssetAspect::RssFeed WebGUI::Asset::Wobject);
|
||||
use WebGUI::Macro;
|
||||
use XML::FeedPP;
|
||||
|
||||
|
|
@ -116,7 +117,7 @@ sub definition {
|
|||
className=>'WebGUI::Asset::Wobject::SyndicatedContent',
|
||||
properties=>\%properties
|
||||
});
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
return $class->next::method($session, $definition);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -129,6 +130,7 @@ Combines all feeds into a single XML::FeedPP object.
|
|||
|
||||
sub generateFeed {
|
||||
my $self = shift;
|
||||
my $limit = shift || $self->get('maxHeadlines');
|
||||
my $feed = XML::FeedPP::Atom->new();
|
||||
my $log = $self->session->log;
|
||||
|
||||
|
|
@ -173,8 +175,8 @@ sub generateFeed {
|
|||
# sort them by date
|
||||
$feed->sort_item();
|
||||
|
||||
# limit the feed to the maxium number of headlines
|
||||
$feed->limit_item($self->get('maxHeadlines'));
|
||||
# limit the feed to the maximum number of headlines (or the feed generator limit).
|
||||
$feed->limit_item($limit);
|
||||
|
||||
# mark this asset as updated
|
||||
$self->update({}) if ($newlyCached);
|
||||
|
|
@ -184,6 +186,52 @@ sub generateFeed {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getFeed ()
|
||||
|
||||
Override the one in the parent...
|
||||
|
||||
=cut
|
||||
|
||||
sub getFeed {
|
||||
my $self = shift;
|
||||
my $feed = shift;
|
||||
foreach my $item ($self->generateFeed( $self->get('itemsPerFeed') )->get_item) {
|
||||
my $set_permalink_false = 0;
|
||||
my $new_item = $feed->add_item( $item );
|
||||
if (!$new_item->guid) {
|
||||
if ($new_item->link) {
|
||||
$new_item->guid( $new_item->link );
|
||||
} else {
|
||||
$new_item->guid( $self->session->id->generate );
|
||||
$set_permalink_false = 1;
|
||||
}
|
||||
}
|
||||
$new_item->guid( $new_item->guid, isPermaLink => 0 ) if $set_permalink_false;
|
||||
}
|
||||
$feed->title( $self->get('feedTitle') || $self->get('title') );
|
||||
$feed->description( $self->get('feedDescription') || $self->get('synopsis') );
|
||||
$feed->pubDate( $self->getContentLastModified );
|
||||
$feed->copyright( $self->get('feedCopyright') );
|
||||
$feed->link( $self->getUrl );
|
||||
# $feed->language( $lang );
|
||||
if ($self->get('feedImage')) {
|
||||
my $storage = WebGUI::Storage->get($self->session, $self->get('feedImage'));
|
||||
my @files = @{ $storage->getFiles };
|
||||
if (scalar @files) {
|
||||
$feed->image(
|
||||
$storage->getUrl( $files[0] ),
|
||||
$self->get('feedImageDescription') || $self->getTitle,
|
||||
$self->get('feedImageUrl') || $self->getUrl,
|
||||
$self->get('feedImageDescription') || $self->getTitle,
|
||||
( $storage->getSizeInPixels( $files[0] ) ) # expands to width and height
|
||||
);
|
||||
}
|
||||
}
|
||||
return $feed;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getTemplateVariables
|
||||
|
||||
Returns a hash reference of template variables.
|
||||
|
|
@ -198,11 +246,11 @@ sub getTemplateVariables {
|
|||
my ($self, $feed) = @_;
|
||||
my @items = $feed->get_item;
|
||||
my %var;
|
||||
$var{channel_title} = WebGUI::HTML::filter($feed->title, 'javascript');
|
||||
$var{channel_title} = WebGUI::HTML::filter(scalar $feed->title, 'javascript');
|
||||
$var{channel_description} = WebGUI::HTML::filter(scalar($feed->description), 'javascript');
|
||||
$var{channel_date} = WebGUI::HTML::filter(scalar($feed->get_pubDate_epoch), 'javascript');
|
||||
$var{channel_copyright} = WebGUI::HTML::filter(scalar($feed->copyright), 'javascript');
|
||||
$var{channel_link} = WebGUI::HTML::filter($feed->link, 'javascript');
|
||||
$var{channel_link} = WebGUI::HTML::filter(scalar $feed->link, 'javascript');
|
||||
my @image = $feed->image;
|
||||
$var{channel_image_url} = WebGUI::HTML::filter($image[0], 'javascript');
|
||||
$var{channel_image_title} = WebGUI::HTML::filter($image[1], 'javascript');
|
||||
|
|
@ -212,12 +260,12 @@ sub getTemplateVariables {
|
|||
$var{channel_image_height} = WebGUI::HTML::filter($image[5], 'javascript');
|
||||
foreach my $object (@items) {
|
||||
my %item;
|
||||
$item{title} = WebGUI::HTML::filter($object->title, 'javascript');
|
||||
$item{date} = WebGUI::HTML::filter($object->get_pubDate_epoch, 'javascript');
|
||||
$item{category} = WebGUI::HTML::filter($object->category, 'javascript');
|
||||
$item{author} = WebGUI::HTML::filter($object->author, 'javascript');
|
||||
$item{guid} = WebGUI::HTML::filter($object->guid, 'javascript');
|
||||
$item{link} = WebGUI::HTML::filter($object->link, 'javascript');
|
||||
$item{title} = WebGUI::HTML::filter(scalar $object->title, 'javascript');
|
||||
$item{date} = WebGUI::HTML::filter(scalar $object->get_pubDate_epoch, 'javascript');
|
||||
$item{category} = WebGUI::HTML::filter(scalar $object->category, 'javascript');
|
||||
$item{author} = WebGUI::HTML::filter(scalar $object->author, 'javascript');
|
||||
$item{guid} = WebGUI::HTML::filter(scalar $object->guid, 'javascript');
|
||||
$item{link} = WebGUI::HTML::filter(scalar $object->link, 'javascript');
|
||||
$item{description} = WebGUI::HTML::filter(scalar($object->description), 'javascript');
|
||||
$item{descriptionFirst100words} = $item{description};
|
||||
$item{descriptionFirst100words} =~ s/(((\S+)\s+){100}).*/$1/s;
|
||||
|
|
@ -256,15 +304,10 @@ See WebGUI::Asset::prepareView() for details.
|
|||
|
||||
sub prepareView {
|
||||
my $self = shift;
|
||||
$self->SUPER::prepareView();
|
||||
$self->next::method;
|
||||
my $template = WebGUI::Asset::Template->new($self->session, $self->get("templateId"));
|
||||
$template->prepare($self->getMetaDataAsTemplateVariables);
|
||||
$self->{_viewTemplate} = $template;
|
||||
my $title = $self->get("title");
|
||||
my $style = $self->session->style;
|
||||
$style->setLink($self->getUrl("func=viewRss"), { rel=>'alternate', type=>'application/rss+xml', title=>$title.' (RSS)' });
|
||||
$style->setLink($self->getUrl("func=viewRdf"), { rel=>'alternate', type=>'application/rdf+xml', title=>$title.' (RDF)' });
|
||||
$style->setLink($self->getUrl("func=viewAtom"), { rel=>'alternate', type=>'application/atom+xml', title=>$title.' (Atom)' });
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -279,7 +322,7 @@ See WebGUI::Asset::purgeCache() for details.
|
|||
sub purgeCache {
|
||||
my $self = shift;
|
||||
WebGUI::Cache->new($self->session,"view_".$self->getId)->delete;
|
||||
$self->SUPER::purgeCache;
|
||||
$self->next::method;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -318,59 +361,7 @@ See WebGUI::Asset::Wobject::www_view() for details.
|
|||
sub www_view {
|
||||
my $self = shift;
|
||||
$self->session->http->setCacheControl($self->get("cacheTimeout"));
|
||||
$self->SUPER::www_view(@_);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_viewAtom ( )
|
||||
|
||||
Emit an Atom 0.3 feed.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_viewAtom {
|
||||
my $self = shift;
|
||||
my $feed = $self->generateFeed;
|
||||
my $atom = XML::FeedPP::Atom->new;
|
||||
$atom->merge($feed);
|
||||
$self->session->http->setMimeType('application/atom+xml');
|
||||
return $atom->to_string;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_viewRdf ( )
|
||||
|
||||
Emit an RSS 1.0 / RDF feed.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_viewRdf {
|
||||
my $self = shift;
|
||||
my $feed = $self->generateFeed;
|
||||
my $rdf = XML::FeedPP::RDF->new;
|
||||
$rdf->merge($feed);
|
||||
$self->session->http->setMimeType('application/rdf+xml');
|
||||
return $rdf->to_string;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_viewRss ( )
|
||||
|
||||
Emit an RSS 2.0 feed.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_viewRss {
|
||||
my $self = shift;
|
||||
my $feed = $self->generateFeed;
|
||||
my $rss = XML::FeedPP::RSS->new;
|
||||
$rss->merge($feed);
|
||||
$self->session->http->setMimeType('application/rss+xml');
|
||||
return $rss->to_string;
|
||||
$self->next::method(@_);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -412,6 +403,20 @@ sub www_viewRSS10 {
|
|||
return $self->www_viewRdf;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_viewRSS ( )
|
||||
|
||||
Deprecated. Use www_viewRss() instead.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_viewRSS {
|
||||
my $self = shift;
|
||||
return $self->www_viewRss;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_viewRSS20 ( )
|
||||
|
|
|
|||
|
|
@ -308,6 +308,42 @@ sub duplicate {
|
|||
return $newAsset;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 duplicateThing ( thingId )
|
||||
|
||||
Duplicates a thing.
|
||||
|
||||
=head3 thingId
|
||||
|
||||
The id of the Thing that will be duplicated.
|
||||
|
||||
=cut
|
||||
|
||||
sub duplicateThing {
|
||||
|
||||
my $self = shift;
|
||||
my $oldThingId = shift;
|
||||
my $db = $self->session->db;
|
||||
|
||||
my $thingProperties = $self->getThing($oldThingId);
|
||||
$thingProperties->{thingId} = 'new';
|
||||
$thingProperties->{label} = $thingProperties->{label}.' (copy)';
|
||||
|
||||
my $newThingId = $self->addThing($thingProperties);
|
||||
my $fields = $db->buildArrayRefOfHashRefs('select * from Thingy_fields where assetId=? and thingId=?'
|
||||
,[$self->getId,$oldThingId]);
|
||||
foreach my $field (@$fields) {
|
||||
# set thingId to newly created thing's id.
|
||||
$field->{thingId} = $newThingId;
|
||||
$self->addField($field,0);
|
||||
}
|
||||
|
||||
return $newThingId;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 deleteField ( fieldId , thingId )
|
||||
|
|
@ -641,7 +677,10 @@ sub getEditFieldForm {
|
|||
}
|
||||
|
||||
my $dialogPrefix;
|
||||
if ($fieldId eq "new"){
|
||||
if ($field->{oldFieldId}){
|
||||
$dialogPrefix = "edit_".$field->{oldFieldId}."_Dialog_copy";
|
||||
}
|
||||
elsif($fieldId eq "new"){
|
||||
$dialogPrefix = "addDialog";
|
||||
}
|
||||
else{
|
||||
|
|
@ -1436,6 +1475,26 @@ sub www_deleteFieldConfirm {
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_duplicateThing ( )
|
||||
|
||||
Duplicates a Thing.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_duplicateThing {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $thingId = $session->form->process("thingId");
|
||||
return $session->privilege->insufficient() unless $self->canEdit;
|
||||
|
||||
$self->duplicateThing($thingId);
|
||||
|
||||
return $self->www_manage;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_copyThingData( )
|
||||
|
|
@ -1714,7 +1773,10 @@ sub www_editThing {
|
|||
." <td style='width:100px;' valign='top' class='formDescription'>".$field->{label}."</td>\n"
|
||||
." <td style='width:370px;'>".$formElement."</td>\n"
|
||||
." <td style='width:120px;' valign='top'> <input onClick=\"editListItem('".$self->session->url->page()
|
||||
."?func=editField;fieldId=".$field->{fieldId}.";thingId=".$thingId."','".$field->{fieldId}."')\" value='".$i18n->get('Edit','Icon')."' type='button'>"
|
||||
."?func=editField;fieldId=".$field->{fieldId}.";thingId=".$thingId."','".$field->{fieldId}."')\" value='Edit' type='button'>"
|
||||
." <input onClick=\"editListItem('".$self->session->url->page()
|
||||
."?func=editField;copy=1;fieldId=".$field->{fieldId}.";thingId=".$thingId."','".$field->{fieldId}
|
||||
."','copy')\" value='Copy' type='button'>"
|
||||
."<input onClick=\"deleteListItem('".$self->session->url->page()."','".$field->{fieldId}."','".$thingId."')\" "
|
||||
."value='".$i18n->get('Delete','Icon')."' type='button'></td>\n</tr>\n</table>\n</li>\n";
|
||||
|
||||
|
|
@ -2055,12 +2117,19 @@ Returns the html for a pop-up dialog to add or edit a field.
|
|||
|
||||
sub www_editField {
|
||||
|
||||
my $self = shift;
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my (%properties,$thingId,$fieldId,$dialogBody);
|
||||
return $self->session->privilege->insufficient() unless $self->canEdit;
|
||||
$fieldId = $self->session->form->process("fieldId");
|
||||
$thingId = $self->session->form->process("thingId");
|
||||
%properties = $self->session->db->quickHash("select * from Thingy_fields where thingId=".$self->session->db->quote($thingId)." and fieldId = ".$self->session->db->quote($fieldId)." and assetId = ".$self->session->db->quote($self->get("assetId")));
|
||||
return $session->privilege->insufficient() unless $self->canEdit;
|
||||
$fieldId = $session->form->process("fieldId");
|
||||
$thingId = $session->form->process("thingId");
|
||||
%properties = $session->db->quickHash("select * from Thingy_fields where thingId=? and fieldId=? and assetId=?",
|
||||
[$thingId,$fieldId,$self->get("assetId")]);
|
||||
if($session->form->process("copy")){
|
||||
$properties{oldFieldId} = $properties{fieldId};
|
||||
$properties{fieldId} = 'new';
|
||||
$properties{label} = $properties{label}.' (copy)';
|
||||
}
|
||||
$dialogBody = $self->getEditFieldForm(\%properties);
|
||||
$self->session->output->print($dialogBody->print);
|
||||
return "chunked";
|
||||
|
|
@ -2868,6 +2937,8 @@ sub www_manage {
|
|||
"",$i18n->get('delete thing warning')),
|
||||
'thing_editUrl' => $session->url->append($url, 'func=editThing;thingId='.$thing->{thingId}),
|
||||
'thing_editIcon' => $session->icon->edit('func=editThing;thingId='.$thing->{thingId}),
|
||||
'thing_copyUrl' => $session->url->append($url, 'func=duplicateThing;thingId='.$thing->{thingId}),
|
||||
'thing_copyIcon' => $session->icon->copy('func=duplicateThing;thingId='.$thing->{thingId}),
|
||||
'thing_addUrl' => $session->url->append($url,
|
||||
'func=editThingData;thingId='.$thing->{thingId}.';thingDataId=new'),
|
||||
'thing_searchUrl' => $session->url->append($url, 'func=search;thingId='.$thing->{thingId}),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ package WebGUI::Asset::Wobject::WikiMaster;
|
|||
# http://www.plainblack.com info@plainblack.com
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
use base 'WebGUI::Asset::Wobject';
|
||||
use Class::C3;
|
||||
use base qw(WebGUI::AssetAspect::RssFeed WebGUI::Asset::Wobject);
|
||||
use strict;
|
||||
use Tie::IxHash;
|
||||
use WebGUI::International;
|
||||
|
|
@ -70,6 +71,7 @@ sub appendRecentChanges {
|
|||
username=>$user->username,
|
||||
date=>$self->session->datetime->epochToHuman($asset->get("revisionDate")),
|
||||
isAvailable=>$isAvailable,
|
||||
assetId=>$id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -139,7 +141,7 @@ sub autolinkHtml {
|
|||
#-------------------------------------------------------------------
|
||||
sub canAdminister {
|
||||
my $self = shift;
|
||||
return $self->session->user->isInGroup($self->get('groupToAdminister')) || $self->SUPER::canEdit;
|
||||
return $self->session->user->isInGroup($self->get('groupToAdminister')) || $self->WebGUI::Asset::Wobject::canEdit;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -164,7 +166,7 @@ sub canEdit {
|
|||
) &&
|
||||
$self->canEditPages
|
||||
) || # account for new posts
|
||||
$self->SUPER::canEdit()
|
||||
$self->next::method()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -337,13 +339,44 @@ sub definition {
|
|||
properties => \%properties,
|
||||
};
|
||||
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
return $class->next::method($session, $definition);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getRssFeedItems ()
|
||||
|
||||
Returns an array reference of hash references. Each hash reference has a title,
|
||||
description, link, and date field. The date field can be either an epoch date, an RFC 1123
|
||||
date, or a ISO date in the format of YYYY-MM-DD HH:MM::SS. Optionally specify an
|
||||
author, and a guid field.
|
||||
|
||||
=cut
|
||||
|
||||
sub getRssFeedItems {
|
||||
my $self = shift;
|
||||
my $vars = {};
|
||||
$self->appendRecentChanges( $vars, $self->get('itemsPerFeed') );
|
||||
my $var = [];
|
||||
foreach my $item ( @{ $vars->{recentChanges} } ) {
|
||||
my $asset = WebGUI::Asset->newByDynamicClass( $self->session, $item->{assetId} );
|
||||
push @{ $var }, {
|
||||
'link' => $asset->getUrl,
|
||||
'guid' => $item->{ 'assetId' } . $asset->get( 'revisionDate' ),
|
||||
'title' => $asset->getTitle,
|
||||
'description' => $item->{ 'actionTaken' },
|
||||
'date' => $item->{ 'date' },
|
||||
'author' => $item->{ 'username' },
|
||||
};
|
||||
}
|
||||
|
||||
return $var;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub prepareView {
|
||||
my $self = shift;
|
||||
$self->SUPER::prepareView;
|
||||
$self->next::method;
|
||||
$self->{_frontPageTemplate} =
|
||||
WebGUI::Asset::Template->new($self->session, $self->get('frontPageTemplateId'));
|
||||
$self->{_frontPageTemplate}->prepare;
|
||||
|
|
@ -355,7 +388,7 @@ sub processPropertiesFromFormPost {
|
|||
my $groupsChanged =
|
||||
(($self->session->form->process('groupIdView') ne $self->get('groupIdView'))
|
||||
or ($self->session->form->process('groupIdEdit') ne $self->get('groupIdEdit')));
|
||||
my $ret = $self->SUPER::processPropertiesFromFormPost(@_);
|
||||
my $ret = $self->next::method(@_);
|
||||
if ($groupsChanged) {
|
||||
foreach my $child (@{$self->getLineage(['children'], {returnObjects => 1})}) {
|
||||
$child->update({ groupIdView => $self->get('groupIdView'),
|
||||
|
|
|
|||
|
|
@ -18,6 +18,10 @@ use WebGUI::International;
|
|||
use WebGUI::Utility;
|
||||
use base 'WebGUI::Asset::Wobject';
|
||||
|
||||
# To get an installer for your wobject, add the Installable AssetAspect
|
||||
# See WebGUI::AssetAspect::Installable and sbin/installClass.pl for more
|
||||
# details
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( )
|
||||
|
|
@ -29,46 +33,43 @@ getEditForm method is unnecessary/redundant/useless.
|
|||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_NewWobject');
|
||||
my %properties;
|
||||
tie %properties, 'Tie::IxHash';
|
||||
%properties = (
|
||||
templateId =>{
|
||||
|
||||
#See the list of field/control types in /lib/WebGUI/Form/
|
||||
fieldType=>"template",
|
||||
|
||||
defaultValue=>'NewWobjectTmpl00000001',
|
||||
tab=>"display",
|
||||
|
||||
#www_editSave will ignore anyone's attempts to update this field if this is set to 1
|
||||
noFormPost=>0,
|
||||
|
||||
#This is an option specific to the template fieldType.
|
||||
namespace=>"NewWobject",
|
||||
|
||||
#This is what will appear when the user hovers the mouse over the label
|
||||
# of your form field.
|
||||
hoverHelp=>$i18n->get('templateId label description'),
|
||||
|
||||
# This is the text that will appear to the left of your form field.
|
||||
label=>$i18n->get('templateId label'),
|
||||
}
|
||||
);
|
||||
push(@{$definition}, {
|
||||
assetName=>$i18n->get('assetName'),
|
||||
icon=>'newWobject.gif',
|
||||
autoGenerateForms=>1,
|
||||
tableName=>'NewWobject',
|
||||
className=>'WebGUI::Asset::Wobject::NewWobject',
|
||||
properties=>\%properties
|
||||
});
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
}
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new( $session, 'Asset_NewWobject' );
|
||||
tie my %properties, 'Tie::IxHash', (
|
||||
templateId => {
|
||||
|
||||
#See the list of field/control types in /lib/WebGUI/Form/
|
||||
fieldType => "template",
|
||||
|
||||
defaultValue => 'NewWobjectTmpl00000001',
|
||||
tab => "display",
|
||||
|
||||
#www_editSave will ignore anyone's attempts to update this field if this is set to 1
|
||||
noFormPost => 0,
|
||||
|
||||
#This is an option specific to the template fieldType.
|
||||
namespace => "NewWobject",
|
||||
|
||||
#This is what will appear when the user hovers the mouse over the label
|
||||
# of your form field.
|
||||
hoverHelp => $i18n->get('templateId label description'),
|
||||
|
||||
# This is the text that will appear to the left of your form field.
|
||||
label => $i18n->get('templateId label'),
|
||||
}
|
||||
);
|
||||
push @{$definition}, {
|
||||
assetName => $i18n->get('assetName'),
|
||||
icon => 'newWobject.gif',
|
||||
autoGenerateForms => 1,
|
||||
tableName => 'NewWobject',
|
||||
className => 'WebGUI::Asset::Wobject::NewWobject',
|
||||
properties => \%properties
|
||||
};
|
||||
return $class->SUPER::definition( $session, $definition );
|
||||
} ## end sub definition
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -81,9 +82,9 @@ wobject instances, you will need to duplicate them here.
|
|||
=cut
|
||||
|
||||
sub duplicate {
|
||||
my $self = shift;
|
||||
my $newAsset = $self->SUPER::duplicate(@_);
|
||||
return $newAsset;
|
||||
my $self = shift;
|
||||
my $newAsset = $self->SUPER::duplicate(@_);
|
||||
return $newAsset;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -96,16 +97,16 @@ This method is optional if you set autoGenerateForms=1 in the definition.
|
|||
=cut
|
||||
|
||||
sub getEditForm {
|
||||
my $self = shift;
|
||||
my $tabform = $self->SUPER::getEditForm();
|
||||
my $self = shift;
|
||||
my $tabform = $self->SUPER::getEditForm();
|
||||
|
||||
$tabform->getTab("display")->template(
|
||||
-value=>$self->getValue("templateId"),
|
||||
-label=>WebGUI::International::get("template_label","Asset_NewWobject"),
|
||||
-namespace=>"NewWobject"
|
||||
);
|
||||
|
||||
return $tabform;
|
||||
$tabform->getTab("display")->template(
|
||||
value => $self->getValue("templateId"),
|
||||
label => WebGUI::International::get( "template_label", "Asset_NewWobject" ),
|
||||
namespace => "NewWobject"
|
||||
);
|
||||
|
||||
return $tabform;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -117,14 +118,13 @@ See WebGUI::Asset::prepareView() for details.
|
|||
=cut
|
||||
|
||||
sub prepareView {
|
||||
my $self = shift;
|
||||
$self->SUPER::prepareView();
|
||||
my $template = WebGUI::Asset::Template->new($self->session, $self->get("templateId"));
|
||||
$template->prepare;
|
||||
$self->{_viewTemplate} = $template;
|
||||
my $self = shift;
|
||||
$self->SUPER::prepareView();
|
||||
my $template = WebGUI::Asset::Template->new( $self->session, $self->get("templateId") );
|
||||
$template->prepare($self->getMetaDataAsTemplateVariables);
|
||||
$self->{_viewTemplate} = $template;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 purge ( )
|
||||
|
|
@ -137,10 +137,11 @@ wobject instances, you will need to purge them here.
|
|||
=cut
|
||||
|
||||
sub purge {
|
||||
my $self = shift;
|
||||
#purge your wobject-specific data here. This does not include fields
|
||||
# you create for your NewWobject asset/wobject table.
|
||||
return $self->SUPER::purge;
|
||||
my $self = shift;
|
||||
|
||||
#purge your wobject-specific data here. This does not include fields
|
||||
# you create for your NewWobject asset/wobject table.
|
||||
return $self->SUPER::purge;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -153,16 +154,16 @@ to be displayed within the page style.
|
|||
=cut
|
||||
|
||||
sub view {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
|
||||
#This automatically creates template variables for all of your wobject's properties.
|
||||
my $var = $self->get;
|
||||
|
||||
#This is an example of debugging code to help you diagnose problems.
|
||||
#WebGUI::ErrorHandler::warn($self->get("templateId"));
|
||||
|
||||
return $self->processTemplate($var, undef, $self->{_viewTemplate});
|
||||
#This automatically creates template variables for all of your wobject's properties.
|
||||
my $var = $self->get;
|
||||
|
||||
#This is an example of debugging code to help you diagnose problems.
|
||||
#$session->log->warn($self->get("templateId"));
|
||||
|
||||
return $self->processTemplate( $var, undef, $self->{_viewTemplate} );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -183,60 +184,6 @@ adminConsole views.
|
|||
# return $self->getAdminConsole->render($self->getEditForm->print, $i18n->get("edit title"));
|
||||
#}
|
||||
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# Everything below here is to make it easier to install your custom
|
||||
# wobject, but has nothing to do with wobjects in general
|
||||
#-------------------------------------------------------------------
|
||||
# cd /data/WebGUI/lib
|
||||
# perl -MWebGUI::Asset::Wobject::NewWobject -e install www.example.com.conf [ /path/to/WebGUI ]
|
||||
# - or -
|
||||
# perl -MWebGUI::Asset::Wobject::NewWobject -e uninstall www.example.com.conf [ /path/to/WebGUI ]
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
||||
use base 'Exporter';
|
||||
our @EXPORT = qw(install uninstall);
|
||||
use WebGUI::Session;
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub install {
|
||||
my $config = $ARGV[0];
|
||||
my $home = $ARGV[1] || "/data/WebGUI";
|
||||
die "usage: perl -MWebGUI::Asset::Wobject::NewWobject -e install www.example.com.conf\n" unless ($home && $config);
|
||||
print "Installing asset.\n";
|
||||
my $session = WebGUI::Session->open($home, $config);
|
||||
$session->config->addToArray("assets","WebGUI::Asset::Wobject::NewWobject");
|
||||
$session->db->write("create table NewWobject (
|
||||
assetId varchar(22) binary not null,
|
||||
revisionDate bigint not null,
|
||||
primary key (assetId, revisionDate)
|
||||
)");
|
||||
$session->var->end;
|
||||
$session->close;
|
||||
print "Done. Please restart Apache.\n";
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub uninstall {
|
||||
my $config = $ARGV[0];
|
||||
my $home = $ARGV[1] || "/data/WebGUI";
|
||||
die "usage: perl -MWebGUI::Asset::Wobject::NewWobject -e uninstall www.example.com.conf\n" unless ($home && $config);
|
||||
print "Uninstalling asset.\n";
|
||||
my $session = WebGUI::Session->open($home, $config);
|
||||
$session->config->deleteFromArray("assets","WebGUI::Asset::Wobject::NewWobject");
|
||||
my $rs = $session->db->read("select assetId from asset where className='WebGUI::Asset::Wobject::NewWobject'");
|
||||
while (my ($id) = $rs->array) {
|
||||
my $asset = WebGUI::Asset->new($session, $id, "WebGUI::Asset::Wobject::NewWobject");
|
||||
$asset->purge if defined $asset;
|
||||
}
|
||||
$session->db->write("drop table NewWobject");
|
||||
$session->var->end;
|
||||
$session->close;
|
||||
print "Done. Please restart Apache.\n";
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
#vim:ft=perl
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ use Tie::IxHash;
|
|||
use base 'WebGUI::Asset';
|
||||
use WebGUI::Utility;
|
||||
|
||||
|
||||
# To get an installer for your wobject, add the Installable AssetAspect
|
||||
# See WebGUI::AssetAspect::Installable and sbin/installClass.pl for more
|
||||
# details
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
|
@ -40,21 +42,19 @@ These methods are available from this class:
|
|||
|
||||
=cut
|
||||
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 addRevision
|
||||
|
||||
This method exists for demonstration purposes only. The superclass
|
||||
handles revisions to NewAsset Assets.
|
||||
This method exists for demonstration purposes only. The superclass
|
||||
handles revisions to NewAsset Assets.
|
||||
|
||||
=cut
|
||||
|
||||
sub addRevision {
|
||||
my $self = shift;
|
||||
my $newSelf = $self->SUPER::addRevision(@_);
|
||||
return $newSelf;
|
||||
my $self = shift;
|
||||
my $newSelf = $self->SUPER::addRevision(@_);
|
||||
return $newSelf;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -73,66 +73,68 @@ A hash reference passed in from a subclass definition.
|
|||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my %properties;
|
||||
tie %properties, 'Tie::IxHash';
|
||||
my $i18n = WebGUI::International->new($session, "Asset_NewAsset");
|
||||
%properties = (
|
||||
templateId => {
|
||||
# Determines which tab this property appears in
|
||||
tab=>"display",
|
||||
#See the list of field/control types in /lib/WebGUI/Form/
|
||||
fieldType=>"template",
|
||||
defaultValue=>'NewAssetTmpl0000000001',
|
||||
#www_editSave will ignore anyone's attempts to update this field if this is set to 1
|
||||
noFormPost=>0,
|
||||
#This is an option specific to the template fieldType.
|
||||
namespace=>"NewAsset",
|
||||
#This is what will appear when the user hovers the mouse over the label
|
||||
# of your form field.
|
||||
hoverHelp=>$i18n->get('templateId label description'),
|
||||
# This is the text that will appear to the left of your form field.
|
||||
label=>$i18n->get('templateId label')
|
||||
},
|
||||
foo => {
|
||||
tab=>"properties",
|
||||
fieldType=>"text",
|
||||
defaultValue=>undef,
|
||||
label=>$i18n->get("foo label"),
|
||||
hoverHelp=>$i18n->get("foo label help")
|
||||
}
|
||||
);
|
||||
push(@{$definition}, {
|
||||
assetName=>$i18n->get('assetName'),
|
||||
icon=>'NewAsset.gif',
|
||||
autoGenerateForms=>1,
|
||||
tableName=>'NewAsset',
|
||||
className=>'WebGUI::Asset::NewAsset',
|
||||
properties=>\%properties
|
||||
});
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
}
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new( $session, "Asset_NewAsset" );
|
||||
tie my %properties, 'Tie::IxHash', (
|
||||
templateId => {
|
||||
|
||||
# Determines which tab this property appears in
|
||||
tab => "display",
|
||||
|
||||
#See the list of field/control types in /lib/WebGUI/Form/
|
||||
fieldType => "template",
|
||||
defaultValue => 'NewAssetTmpl0000000001',
|
||||
|
||||
#www_editSave will ignore anyone's attempts to update this field if this is set to 1
|
||||
noFormPost => 0,
|
||||
|
||||
#This is an option specific to the template fieldType.
|
||||
namespace => "NewAsset",
|
||||
|
||||
#This is what will appear when the user hovers the mouse over the label
|
||||
# of your form field.
|
||||
hoverHelp => $i18n->get('templateId label description'),
|
||||
|
||||
# This is the text that will appear to the left of your form field.
|
||||
label => $i18n->get('templateId label')
|
||||
},
|
||||
foo => {
|
||||
tab => "properties",
|
||||
fieldType => "text",
|
||||
defaultValue => undef,
|
||||
label => $i18n->get("foo label"),
|
||||
hoverHelp => $i18n->get("foo label help")
|
||||
},
|
||||
);
|
||||
push @{$definition}, {
|
||||
assetName => $i18n->get('assetName'),
|
||||
icon => 'NewAsset.gif',
|
||||
autoGenerateForms => 1,
|
||||
tableName => 'NewAsset',
|
||||
className => 'WebGUI::Asset::NewAsset',
|
||||
properties => \%properties,
|
||||
};
|
||||
return $class->SUPER::definition( $session, $definition );
|
||||
} ## end sub definition
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 duplicate
|
||||
|
||||
This method exists for demonstration purposes only. The superclass
|
||||
handles duplicating NewAsset Assets. This method will be called
|
||||
whenever a copy action is executed
|
||||
This method exists for demonstration purposes only. The superclass
|
||||
handles duplicating NewAsset Assets. This method will be called
|
||||
whenever a copy action is executed
|
||||
|
||||
=cut
|
||||
|
||||
sub duplicate {
|
||||
my $self = shift;
|
||||
my $newAsset = $self->SUPER::duplicate(@_);
|
||||
return $newAsset;
|
||||
my $self = shift;
|
||||
my $newAsset = $self->SUPER::duplicate(@_);
|
||||
return $newAsset;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 indexContent ( )
|
||||
|
|
@ -142,12 +144,11 @@ Making private. See WebGUI::Asset::indexContent() for additonal details.
|
|||
=cut
|
||||
|
||||
sub indexContent {
|
||||
my $self = shift;
|
||||
my $indexer = $self->SUPER::indexContent;
|
||||
$indexer->setIsPublic(0);
|
||||
my $self = shift;
|
||||
my $indexer = $self->SUPER::indexContent;
|
||||
$indexer->setIsPublic(0);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 prepareView ( )
|
||||
|
|
@ -157,14 +158,13 @@ See WebGUI::Asset::prepareView() for details.
|
|||
=cut
|
||||
|
||||
sub prepareView {
|
||||
my $self = shift;
|
||||
$self->SUPER::prepareView();
|
||||
my $template = WebGUI::Asset::Template->new($self->session, $self->get("templateId"));
|
||||
$template->prepare;
|
||||
$self->{_viewTemplate} = $template;
|
||||
my $self = shift;
|
||||
$self->SUPER::prepareView();
|
||||
my $template = WebGUI::Asset::Template->new( $self->session, $self->get("templateId") );
|
||||
$template->prepare($self->getMetaDataAsTemplateVariables);
|
||||
$self->{_viewTemplate} = $template;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 processPropertiesFromFormPost ( )
|
||||
|
|
@ -176,11 +176,10 @@ when /yourAssetUrl?func=editSave is requested/posted.
|
|||
=cut
|
||||
|
||||
sub processPropertiesFromFormPost {
|
||||
my $self = shift;
|
||||
$self->SUPER::processPropertiesFromFormPost;
|
||||
my $self = shift;
|
||||
$self->SUPER::processPropertiesFromFormPost;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 purge ( )
|
||||
|
|
@ -194,8 +193,8 @@ asset instances, you will need to purge them here.
|
|||
=cut
|
||||
|
||||
sub purge {
|
||||
my $self = shift;
|
||||
return $self->SUPER::purge;
|
||||
my $self = shift;
|
||||
return $self->SUPER::purge;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -207,8 +206,8 @@ This method is called when data is purged by the system.
|
|||
=cut
|
||||
|
||||
sub purgeRevision {
|
||||
my $self = shift;
|
||||
return $self->SUPER::purgeRevision;
|
||||
my $self = shift;
|
||||
return $self->SUPER::purgeRevision;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -220,13 +219,12 @@ method called by the container www_view method.
|
|||
=cut
|
||||
|
||||
sub view {
|
||||
my $self = shift;
|
||||
my $var = $self->get; # $var is a hash reference.
|
||||
$var->{controls} = $self->getToolbar;
|
||||
return $self->processTemplate($var,undef, $self->{_viewTemplate});
|
||||
my $self = shift;
|
||||
my $var = $self->get; # $var is a hash reference.
|
||||
$var->{controls} = $self->getToolbar;
|
||||
return $self->processTemplate( $var, undef, $self->{_viewTemplate} );
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_edit ( )
|
||||
|
|
@ -238,69 +236,14 @@ the module.
|
|||
=cut
|
||||
|
||||
sub www_edit {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return $session->privilege->insufficient() unless $self->canEdit;
|
||||
return $session->privilege->locked() unless $self->canEditIfLocked;
|
||||
my $i18n = WebGUI::International->new($session, 'Asset_NewAsset');
|
||||
return $self->getAdminConsole->render($self->getEditForm->print, $i18n->get('edit asset'));
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return $session->privilege->insufficient() unless $self->canEdit;
|
||||
return $session->privilege->locked() unless $self->canEditIfLocked;
|
||||
my $i18n = WebGUI::International->new( $session, 'Asset_NewAsset' );
|
||||
return $self->getAdminConsole->render( $self->getEditForm->print, $i18n->get('edit asset') );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# Everything below here is to make it easier to install your custom
|
||||
# asset, but has nothing to do with assets in general
|
||||
#-------------------------------------------------------------------
|
||||
# cd /data/WebGUI/lib
|
||||
# perl -MWebGUI::Asset::NewAsset -e install www.example.com.conf [ /path/to/WebGUI ]
|
||||
# - or -
|
||||
# perl -MWebGUI::Asset::NewAsset -e uninstall www.example.com.conf [ /path/to/WebGUI ]
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
||||
use base 'Exporter';
|
||||
our @EXPORT = qw(install uninstall);
|
||||
use WebGUI::Session;
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
sub install {
|
||||
my $config = $ARGV[0];
|
||||
my $home = $ARGV[1] || "/data/WebGUI";
|
||||
die "usage: perl -MWebGUI::Asset::NewAsset -e install www.example.com.conf\n" unless ($home && $config);
|
||||
print "Installing asset.\n";
|
||||
my $session = WebGUI::Session->open($home, $config);
|
||||
$session->config->addToArray("assets","WebGUI::Asset::NewAsset");
|
||||
$session->db->write("create table NewAsset (
|
||||
assetId varchar(22) binary not null,
|
||||
revisionDate bigint not null,
|
||||
primary key (assetId, revisionDate)
|
||||
)");
|
||||
$session->var->end;
|
||||
$session->close;
|
||||
print "Done. Please restart Apache.\n";
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
sub uninstall {
|
||||
my $config = $ARGV[0];
|
||||
my $home = $ARGV[1] || "/data/WebGUI";
|
||||
die "usage: perl -MWebGUI::Asset::NewAsset -e uninstall www.example.com.conf\n" unless ($home && $config);
|
||||
print "Uninstalling asset.\n";
|
||||
my $session = WebGUI::Session->open($home, $config);
|
||||
$session->config->deleteFromArray("assets","WebGUI::Asset::NewAsset");
|
||||
my $rs = $session->db->read("select assetId from asset where className='WebGUI::Asset::NewAsset'");
|
||||
while (my ($id) = $rs->array) {
|
||||
my $asset = WebGUI::Asset->new($session, $id, "WebGUI::Asset::NewAsset");
|
||||
$asset->purge if defined $asset;
|
||||
}
|
||||
$session->db->write("drop table NewAsset");
|
||||
$session->var->end;
|
||||
$session->close;
|
||||
print "Done. Please restart Apache.\n";
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
#vim:ft=perl
|
||||
|
|
|
|||
500
lib/WebGUI/AssetAspect/RssFeed.pm
Normal file
500
lib/WebGUI/AssetAspect/RssFeed.pm
Normal file
|
|
@ -0,0 +1,500 @@
|
|||
package WebGUI::AssetAspect::RssFeed;
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2009 Plain Black Corporation.
|
||||
-------------------------------------------------------------------
|
||||
Please read the legal notices (docs/legal.txt) and the license
|
||||
(docs/license.txt) that came with this distribution before using
|
||||
this software.
|
||||
-------------------------------------------------------------------
|
||||
http://www.plainblack.com info@plainblack.com
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use Class::C3;
|
||||
use WebGUI::Exception;
|
||||
use WebGUI::Storage;
|
||||
use XML::FeedPP;
|
||||
use Path::Class::File;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::AssetAspect::RssFeed
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This is an aspect which exposes an asset's items as an RSS or Atom feed.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Class::C3;
|
||||
use base qw(WebGUI::AssetAspect::RssFeed WebGUI::Asset);
|
||||
|
||||
And then wherever you would call $self->SUPER::someMethodName call $self->next::method instead.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
These methods are available from this class:
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition
|
||||
|
||||
Extends the definition to add the RSS fields.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session,'AssetAspect_RssFeed');
|
||||
my %properties;
|
||||
tie %properties, 'Tie::IxHash';
|
||||
%properties = (
|
||||
itemsPerFeed => {
|
||||
noFormPost => 0,
|
||||
fieldType => "integer",
|
||||
defaultValue => 25,
|
||||
tab => "rss",
|
||||
label => $i18n->get('itemsPerFeed'),
|
||||
hoverHelp => $i18n->get('itemsPerFeed hoverHelp')
|
||||
},
|
||||
feedCopyright => {
|
||||
noFormPost => 0,
|
||||
fieldType => "text",
|
||||
defaultValue => "",
|
||||
tab => "rss",
|
||||
label => $i18n->get('feedCopyright'),
|
||||
hoverHelp => $i18n->get('feedCopyright hoverHelp')
|
||||
},
|
||||
feedTitle => {
|
||||
noFormPost => 0,
|
||||
fieldType => "text",
|
||||
defaultValue => "",
|
||||
tab => "rss",
|
||||
label => $i18n->get('feedTitle'),
|
||||
hoverHelp => $i18n->get('feedTitle hoverHelp')
|
||||
},
|
||||
feedDescription => {
|
||||
noFormPost => 0,
|
||||
fieldType => "textarea",
|
||||
defaultValue => "",
|
||||
tab => "rss",
|
||||
label => $i18n->get('feedDescription'),
|
||||
hoverHelp => $i18n->get('feedDescription hoverHelp')
|
||||
},
|
||||
feedImage => {
|
||||
noFormPost => 0,
|
||||
fieldType => "image",
|
||||
tab => "rss",
|
||||
label => $i18n->get('feedImage'),
|
||||
hoverHelp => $i18n->get('feedImage hoverHelp')
|
||||
},
|
||||
feedImageLink => {
|
||||
noFormPost => 0,
|
||||
fieldType => "url",
|
||||
defaultValue => "",
|
||||
tab => "rss",
|
||||
label => $i18n->get('feedImageLink'),
|
||||
hoverHelp => $i18n->get('feedImageLink hoverHelp')
|
||||
},
|
||||
feedImageDescription => {
|
||||
noFormPost => 0,
|
||||
fieldType => "text",
|
||||
defaultValue => "",
|
||||
tab => "rss",
|
||||
label => $i18n->get('feedImageDescription'),
|
||||
hoverHelp => $i18n->get('feedImageDescription hoverHelp')
|
||||
},
|
||||
feedHeaderLinks => {
|
||||
fieldType => "checkList",
|
||||
allowEmpty => 1,
|
||||
defaultValue => "rss\natom",
|
||||
tab => "rss",
|
||||
options => do {
|
||||
my %headerLinksOptions;
|
||||
tie %headerLinksOptions, 'Tie::IxHash';
|
||||
%headerLinksOptions = (
|
||||
rss => $i18n->get('rssLinkOption'),
|
||||
atom => $i18n->get('atomLinkOption'),
|
||||
rdf => $i18n->get('rdfLinkOption'),
|
||||
);
|
||||
\%headerLinksOptions;
|
||||
},
|
||||
label => $i18n->get('feedHeaderLinks'),
|
||||
hoverHelp => $i18n->get('feedHeaderLinks hoverHelp')
|
||||
},
|
||||
);
|
||||
push(@{$definition}, {
|
||||
autoGenerateForms => 1,
|
||||
tableName => 'assetAspectRssFeed',
|
||||
className => 'WebGUI::AssetAspect::RssFeed',
|
||||
properties => \%properties
|
||||
});
|
||||
return $class->next::method($session, $definition);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 exportAssetCollateral ()
|
||||
|
||||
Extended from WebGUI::Asset and exports the www_viewRss() and
|
||||
www_viewAtom() methods with filenames generated by
|
||||
getStaticAtomFeedUrl() and getStaticRssFeedUrl().
|
||||
|
||||
This method will be called with the following parameters:
|
||||
|
||||
=head3 basePath
|
||||
|
||||
A L<Path::Class> object representing the base filesystem path for this
|
||||
particular asset.
|
||||
|
||||
=head3 params
|
||||
|
||||
A hashref with the quiet, userId, depth, and indexFileName parameters from
|
||||
L<WebGUI::Asset/exportAsHtml>.
|
||||
|
||||
=cut
|
||||
|
||||
sub exportAssetCollateral {
|
||||
# Lots of copy/paste here from AssetExportHtml.pm, since none of the methods there were
|
||||
# directly useful without ginormous refactoring.
|
||||
my $self = shift;
|
||||
my $basepath = shift;
|
||||
my $args = shift;
|
||||
my $reportSession = shift;
|
||||
|
||||
my $reporti18n = WebGUI::International->new($self->session, 'Asset');
|
||||
|
||||
my $basename = $basepath->basename;
|
||||
my $filedir;
|
||||
my $filenameBase;
|
||||
|
||||
# We want our .rss and .atom files to "appear" at the same level as the asset.
|
||||
if ($basename eq 'index.html') {
|
||||
# Get the 2nd ancestor, since the asset url had no dot in it (and it therefore
|
||||
# had its own directory created for it).
|
||||
$filedir = $basepath->parent->parent->absolute->stringify;
|
||||
# Get the parent dir's *path* (essentially the name of the dir) relative to
|
||||
# its own parent dir.
|
||||
$filenameBase = $basepath->parent->relative( $basepath->parent->parent )->stringify;
|
||||
} else {
|
||||
# Get the 1st ancestor, since the asset is a file recognized by apache, so
|
||||
# we want our files in the same dir.
|
||||
$filedir = $basepath->parent->absolute->stringify;
|
||||
# just use the basename.
|
||||
$filenameBase = $basename;
|
||||
}
|
||||
|
||||
if ( $reportSession && !$args->{quiet} ) {
|
||||
$reportSession->output->print('<br />');
|
||||
}
|
||||
|
||||
foreach my $ext (qw( rss atom )) {
|
||||
my $dest = Path::Class::File->new($filedir, $filenameBase . '.' . $ext);
|
||||
|
||||
# tell the user which asset we're exporting.
|
||||
if ( $reportSession && !$args->{quiet} ) {
|
||||
my $message = sprintf $reporti18n->get('exporting page'), $dest->absolute->stringify;
|
||||
$reportSession->output->print(
|
||||
' ' . $message . '<br />');
|
||||
}
|
||||
my $exportSession = WebGUI::Session->open(
|
||||
$self->session->config->getWebguiRoot,
|
||||
$self->session->config->getFilename,
|
||||
undef,
|
||||
undef,
|
||||
$self->session->getId,
|
||||
);
|
||||
|
||||
# open another session as the user doing the exporting...
|
||||
my $selfdupe = WebGUI::Asset->newByDynamicClass( $exportSession, $self->getId );
|
||||
|
||||
# next, get the contents, open the file, and write the contents to the file.
|
||||
my $fh = eval { $dest->open('>:utf8') };
|
||||
if($@) {
|
||||
WebGUI::Error->throw(error => "can't open " . $dest->absolute->stringify . " for writing: $!");
|
||||
$exportSession->close;
|
||||
}
|
||||
$exportSession->asset($selfdupe);
|
||||
$exportSession->output->setHandle($fh);
|
||||
my $contents;
|
||||
if ($ext eq 'rss') {
|
||||
$contents = $selfdupe->www_viewRss;
|
||||
}
|
||||
else {
|
||||
$contents = $selfdupe->www_viewAtom;
|
||||
} # add more for more extensions.
|
||||
|
||||
# chunked content is already printed, no need to print it again
|
||||
unless($contents eq 'chunked') {
|
||||
$exportSession->output->print($contents);
|
||||
}
|
||||
|
||||
$exportSession->close;
|
||||
|
||||
# tell the user we did this asset collateral correctly
|
||||
if ( $reportSession && !$args->{quiet} ) {
|
||||
$reportSession->output->print($reporti18n->get('done'));
|
||||
}
|
||||
}
|
||||
return $self->next::method($basepath, $args, $reportSession);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getRssFeedItems ()
|
||||
|
||||
This method should throw an exception if it's not overridden. Its intention is
|
||||
to be overridden by whatever class is using it and should return an array
|
||||
reference of hash references. Each hash reference should contain at minimum a title,
|
||||
description, link, and date field. The date field can be either an epoch date, an RFC 1123
|
||||
date, or a ISO date in the format of YYYY-MM-DD HH:MM::SS. Optionally specify an
|
||||
author, and a guid field.
|
||||
|
||||
=cut
|
||||
|
||||
sub getRssFeedItems {
|
||||
WebGUI::Error::OverrideMe->throw();
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getAtomFeedUrl ()
|
||||
|
||||
Returns $self->getUrl('func=viewAtom').
|
||||
|
||||
=cut
|
||||
|
||||
sub getAtomFeedUrl {
|
||||
shift->getUrl("func=viewAtom");
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getRdfFeedUrl ()
|
||||
|
||||
Returns $self->getUrl('func=viewRdf').
|
||||
|
||||
=cut
|
||||
|
||||
sub getRdfFeedUrl {
|
||||
shift->getUrl("func=viewRdf");
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getRssFeedUrl ()
|
||||
|
||||
Returns $self->getUrl('func=viewRss').
|
||||
|
||||
=cut
|
||||
|
||||
sub getRssFeedUrl {
|
||||
shift->getUrl("func=viewRss");
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getStaticAtomFeedUrl ()
|
||||
|
||||
Returns the current asset's URL with .atom concatenated onto it.
|
||||
|
||||
=cut
|
||||
|
||||
sub getStaticAtomFeedUrl {
|
||||
my $self = shift;
|
||||
my $url = $self->get("url") . '.atom';
|
||||
$url = $self->session->url->gateway($url);
|
||||
if ($self->get("encryptPage")) {
|
||||
$url = $self->session->url->getSiteURL . $url;
|
||||
$url =~ s/^http:/https:/;
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getStaticRdfFeedUrl ()
|
||||
|
||||
Returns the current asset's URL with .rdf concatenated onto it.
|
||||
|
||||
=cut
|
||||
|
||||
sub getStaticRdfFeedUrl {
|
||||
my $self = shift;
|
||||
my $url = $self->get("url") . '.rdf';
|
||||
$url = $self->session->url->gateway($url);
|
||||
if ($self->get("encryptPage")) {
|
||||
$url = $self->session->url->getSiteURL . $url;
|
||||
$url =~ s/^http:/https:/;
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getStaticRssFeedUrl ()
|
||||
|
||||
Returns the current asset's URL with .rss concatenated onto it.
|
||||
|
||||
=cut
|
||||
|
||||
sub getStaticRssFeedUrl {
|
||||
my $self = shift;
|
||||
my $url = $self->get("url") . '.rss';
|
||||
$url = $self->session->url->gateway($url);
|
||||
if ($self->get("encryptPage")) {
|
||||
$url = $self->session->url->getSiteURL . $url;
|
||||
$url =~ s/^http:/https:/;
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getFeed ()
|
||||
|
||||
Adds the syndicated items to the feed; returns the stringified edition.
|
||||
TODO: convert dates?
|
||||
|
||||
=cut
|
||||
|
||||
sub getFeed {
|
||||
my $self = shift;
|
||||
my $feed = shift;
|
||||
foreach my $item ( @{ $self->getRssFeedItems } ) {
|
||||
my $set_permalink_false = 0;
|
||||
my $new_item = $feed->add_item( %{ $item } );
|
||||
if (!$new_item->guid) {
|
||||
if ($new_item->link) {
|
||||
$new_item->guid( $new_item->link );
|
||||
} else {
|
||||
$new_item->guid( $self->session->id->generate );
|
||||
$set_permalink_false = 1;
|
||||
}
|
||||
}
|
||||
$new_item->guid( $new_item->guid, isPermaLink => 0 ) if $set_permalink_false;
|
||||
}
|
||||
$feed->title( $self->get('feedTitle') || $self->get('title') );
|
||||
$feed->description( $self->get('feedDescription') || $self->get('synopsis') );
|
||||
$feed->pubDate( $self->getContentLastModified );
|
||||
$feed->copyright( $self->get('feedCopyright') );
|
||||
$feed->link( $self->getUrl );
|
||||
# $feed->language( $lang );
|
||||
if ($self->get('feedImage')) {
|
||||
my $storage = WebGUI::Storage->get($self->session, $self->get('feedImage'));
|
||||
my @files = @{ $storage->getFiles };
|
||||
if (scalar @files) {
|
||||
$feed->image(
|
||||
$storage->getUrl( $files[0] ),
|
||||
$self->get('feedImageDescription') || $self->getTitle,
|
||||
$self->get('feedImageUrl') || $self->getUrl,
|
||||
$self->get('feedImageDescription') || $self->getTitle,
|
||||
( $storage->getSizeInPixels( $files[0] ) ) # expands to width and height
|
||||
);
|
||||
}
|
||||
}
|
||||
return $feed;
|
||||
}
|
||||
|
||||
sub prepareView {
|
||||
my $self = shift;
|
||||
$self->addHeaderLinks;
|
||||
return $self->next::method(@_);
|
||||
}
|
||||
|
||||
sub addHeaderLinks {
|
||||
my $self = shift;
|
||||
my $style = $self->session->style;
|
||||
my $title = $self->get('feedTitle') || $self->get("title");
|
||||
my %feeds = map { $_ => 1 } split /\n/, $self->get('feedHeaderLinks');
|
||||
my $addType = keys %feeds > 1;
|
||||
if ($feeds{rss}) {
|
||||
$style->setLink($self->getRssFeedUrl, {
|
||||
rel => 'alternate',
|
||||
type => 'application/rss+xml',
|
||||
title => $title . ( $addType ? ' (RSS)' : ''),
|
||||
});
|
||||
}
|
||||
if ($feeds{atom}) {
|
||||
$style->setLink($self->getAtomFeedUrl, {
|
||||
rel => 'alternate',
|
||||
type => 'application/atom+xml',
|
||||
title => $title . ( $addType ? ' (Atom)' : ''),
|
||||
});
|
||||
}
|
||||
if ($feeds{rdf}) {
|
||||
$style->setLink($self->getRdfFeedUrl, {
|
||||
rel => 'alternate',
|
||||
type => 'application/rdf+xml',
|
||||
title => $title . ( $addType ? ' (RDF)' : ''),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_viewAtom ()
|
||||
|
||||
Return Atom view of the syndicated items.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_viewAtom {
|
||||
my $self = shift;
|
||||
$self->session->http->setMimeType('application/atom+xml');
|
||||
return $self->getFeed( XML::FeedPP::Atom->new )->to_string;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_viewRdf ()
|
||||
|
||||
Return Rdf view of the syndicated items.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_viewRdf {
|
||||
my $self = shift;
|
||||
$self->session->http->setMimeType('application/rdf+xml');
|
||||
return $self->getFeed( XML::FeedPP::RDF->new )->to_string;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_viewRss ()
|
||||
|
||||
Return RSS view of the syndicated items.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_viewRss {
|
||||
my $self = shift;
|
||||
$self->session->http->setMimeType('application/rss+xml');
|
||||
return $self->getFeed( XML::FeedPP::RSS->new )->to_string;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getEditTabs ()
|
||||
|
||||
Adds an RSS tab to the Edit Tabs.
|
||||
|
||||
=cut
|
||||
|
||||
sub getEditTabs {
|
||||
my $self = shift;
|
||||
my $i18n = WebGUI::International->new($self->session,'AssetAspect_RssFeed');
|
||||
return ($self->next::method, ['rss', $i18n->get('RSS tab'), 1]);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
81
lib/WebGUI/AssetCollateral/Sku/Ad/Ad.pm
Normal file
81
lib/WebGUI/AssetCollateral/Sku/Ad/Ad.pm
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
package WebGUI::AssetCollateral::Sku::Ad::Ad;
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2009 Plain Black Corporation.
|
||||
-------------------------------------------------------------------
|
||||
Please read the legal notices (docs/legal.txt) and the license
|
||||
(docs/license.txt) that came with this distribution before using
|
||||
this software.
|
||||
-------------------------------------------------------------------
|
||||
http://www.plainblack.com info@plainblack.com
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
use strict;
|
||||
use base 'WebGUI::Crud';
|
||||
|
||||
#------------------------------------------------
|
||||
|
||||
=head1 crud_definition
|
||||
|
||||
defines the field this crud will contain
|
||||
|
||||
userID = the id of the user that purchased the ad
|
||||
transactionItemid = the id if the transaction item that completes this purchase
|
||||
adId = th id if the ad purchased
|
||||
clicksPurchased = the number of clicks the user purchased
|
||||
impressionsPurchased = the number of impressions the user purchased
|
||||
dateOfPurchase = the date of purchase
|
||||
storedImage = storage for the image
|
||||
isDeleted = boolean that indicates whether the ad has been deleted from the system
|
||||
|
||||
=cut
|
||||
|
||||
sub crud_definition {
|
||||
my ($class, $session) = @_;
|
||||
my $definition = $class->SUPER::crud_definition($session);
|
||||
$definition->{tableName} = 'adSkuPurchase';
|
||||
$definition->{tableKey} = 'adSkuPurchaseId';
|
||||
$definition->{properties} = {
|
||||
userId => {
|
||||
fieldType => 'user',
|
||||
defaultValue => undef,
|
||||
},
|
||||
transactionItemId => {
|
||||
fieldType => 'guid',
|
||||
defaultValue => undef,
|
||||
},
|
||||
adId => {
|
||||
fieldType => 'guid',
|
||||
defaultValue => undef,
|
||||
},
|
||||
clicksPurchased => {
|
||||
fieldType => 'integer',
|
||||
defaultValue => undef,
|
||||
},
|
||||
impressionsPurchased => {
|
||||
fieldType => 'integer',
|
||||
defaultValue => undef,
|
||||
},
|
||||
dateOfPurchase => {
|
||||
fieldType => 'date',
|
||||
defaultValue => undef,
|
||||
},
|
||||
storedImage => {
|
||||
fieldType => 'guid',
|
||||
defaultValue => undef,
|
||||
},
|
||||
isDeleted => {
|
||||
fieldType => 'yesNo',
|
||||
defaultValue => 0,
|
||||
},
|
||||
};
|
||||
return $definition;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
|
@ -317,8 +317,6 @@ sub exportAsHtml {
|
|||
# tell the user which asset we're exporting.
|
||||
unless ($quiet) {
|
||||
my $message = sprintf $i18n->get('exporting page'), $fullPath;
|
||||
$exportSession->var->end;
|
||||
$exportSession->close;
|
||||
$self->session->output->print($message);
|
||||
}
|
||||
|
||||
|
|
@ -335,7 +333,7 @@ sub exportAsHtml {
|
|||
|
||||
# next, tell the asset that we're exporting, so that it can export any
|
||||
# of its collateral or other extra data.
|
||||
eval { $asset->exportAssetCollateral($asset->exportGetUrlAsPath, $args) };
|
||||
eval { $asset->exportAssetCollateral($asset->exportGetUrlAsPath, $args, $session) };
|
||||
if($@) {
|
||||
$returnCode = 0;
|
||||
$message = $@;
|
||||
|
|
@ -389,7 +387,7 @@ sub exportAsHtml {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 exportAssetCollateral ( basePath, params )
|
||||
=head2 exportAssetCollateral ( basePath, params, [ session ] )
|
||||
|
||||
Plug in point for complicated assets (like the CS, the Calendar) to manage
|
||||
exporting their collateral data like other views, children threads and posts,
|
||||
|
|
@ -410,6 +408,10 @@ particular asset.
|
|||
A hashref with the quiet, userId, depth, and indexFileName parameters from
|
||||
L</exportAsHtml>.
|
||||
|
||||
=head3 session
|
||||
|
||||
The session doing the full export. Can be used to report status messages.
|
||||
|
||||
=cut
|
||||
|
||||
sub exportAssetCollateral {
|
||||
|
|
@ -541,7 +543,7 @@ sub exportGetUrlAsPath {
|
|||
my $fileTypes = $config->get('exportBinaryExtensions');
|
||||
|
||||
# get the asset's URL as a URI::URL object for easy parsing of components
|
||||
my $url = URI::URL->new($config->get("sitename")->[0] . $self->getUrl);
|
||||
my $url = URI::URL->new($self->session->url->getSiteURL . $self->getUrl);
|
||||
my @pathComponents = $url->path_components;
|
||||
shift @pathComponents; # first item is the empty string
|
||||
my $filename = pop @pathComponents;
|
||||
|
|
|
|||
|
|
@ -829,7 +829,6 @@ sub setParent {
|
|||
return 0 if ($newParent->getId eq $self->get("parentId")); # don't move it to where it already is
|
||||
return 0 if ($newParent->getId eq $self->getId); # don't move it to itself
|
||||
my $oldLineage = $self->get("lineage");
|
||||
return 0 unless $newParent->canEdit;
|
||||
my $lineage = $newParent->get("lineage").$newParent->getNextChildRank;
|
||||
return 0 if ($lineage =~ m/^$oldLineage/); # can't move it to its own child
|
||||
$self->session->db->beginTransaction;
|
||||
|
|
|
|||
|
|
@ -125,6 +125,15 @@ Imports the data exported by the exportAssetData method. If the asset already ex
|
|||
|
||||
A hash reference containing the exported data.
|
||||
|
||||
=head3 options
|
||||
|
||||
A hash reference of options to change how the import works
|
||||
|
||||
=head4 inheritPermissions
|
||||
|
||||
Forces the all assets in the package to inherit ownerUserId, groupIdView and groupIdEdit
|
||||
from the asset where it is deployed.
|
||||
|
||||
=cut
|
||||
|
||||
sub importAssetData {
|
||||
|
|
@ -212,7 +221,7 @@ sub importAssetCollateralData {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 importPackage ( storageLocation )
|
||||
=head2 importPackage ( storageLocation, options )
|
||||
|
||||
Imports the data from a webgui package file.
|
||||
|
||||
|
|
@ -220,6 +229,10 @@ Imports the data from a webgui package file.
|
|||
|
||||
A reference to a WebGUI::Storage object that contains a webgui package file.
|
||||
|
||||
=head3 options
|
||||
|
||||
A hashref of options that are passed onto importAssetData.
|
||||
|
||||
=cut
|
||||
|
||||
sub importPackage {
|
||||
|
|
|
|||
|
|
@ -298,11 +298,14 @@ sub createAccountSave {
|
|||
$self->saveParams($userId,$self->authMethod,$properties);
|
||||
|
||||
if ($self->getSetting("sendWelcomeMessage")){
|
||||
my $authInfo = "\n\n".$i18n->get(50).": ".$username;
|
||||
$authInfo .= "\n".$i18n->get(51).": ".$password if($password);
|
||||
$authInfo .= "\n\n";
|
||||
WebGUI::Inbox->new($self->session)->addMessage({
|
||||
message => $self->getSetting("welcomeMessage").$authInfo,
|
||||
my $var;
|
||||
$var->{welcomeMessage} = $self->getSetting("welcomeMessage");
|
||||
$var->{newUser_username} = $username;
|
||||
$var->{newUser_password} = $password;
|
||||
my $message = WebGUI::Asset::Template->new($self->session,$self->getSetting('welcomeMessageTemplate'))->process($var);
|
||||
WebGUI::Macro::process($self->session,\$message);
|
||||
WebGUI::Inbox->new($self->session)->addMessage({
|
||||
message => $message,
|
||||
subject => $i18n->get(870),
|
||||
userId => $self->userId,
|
||||
status => 'completed',
|
||||
|
|
|
|||
|
|
@ -273,10 +273,13 @@ sub createAccountSave {
|
|||
to => $profile->{email},
|
||||
subject => $i18n->get('email address validation email subject','AuthWebGUI')
|
||||
});
|
||||
$mail->addText(
|
||||
$i18n->get('email address validation email body','AuthWebGUI') . "\n\n"
|
||||
. $session->url->page("op=auth;method=validateEmail;key=".$key, 'full') . "\n\n"
|
||||
);
|
||||
my $var;
|
||||
$var->{newUser_username} = $username;
|
||||
$var->{activationUrl} = $session->url->page("op=auth;method=validateEmail;key=".$key, 'full');
|
||||
my $text =
|
||||
WebGUI::Asset::Template->new($self->session,$self->getSetting('accountActivationTemplate'))->process($var);
|
||||
WebGUI::Macro::process($self->session,\$text);
|
||||
$mail->addText($text);
|
||||
$mail->addFooter;
|
||||
$mail->send;
|
||||
$self->user->status("Deactivated");
|
||||
|
|
@ -494,7 +497,7 @@ sub editUserSettingsForm {
|
|||
-label => $i18n->get(868,'WebGUI'),
|
||||
-hoverHelp => $i18n->get('868 help','WebGUI'),
|
||||
);
|
||||
$f->textarea(
|
||||
$f->HTMLArea(
|
||||
-name => "webguiWelcomeMessage",
|
||||
-value => $self->session->setting->get("webguiWelcomeMessage"),
|
||||
-label => $i18n->get(869,'WebGUI'),
|
||||
|
|
@ -574,7 +577,21 @@ sub editUserSettingsForm {
|
|||
-label => $i18n->get("password recovery template"),
|
||||
-hoverHelp => $i18n->get("password recovery template help")
|
||||
);
|
||||
return $f->printRowsOnly;
|
||||
$f->template(
|
||||
-name => "webguiWelcomeMessageTemplate",
|
||||
-value => $self->session->setting->get("webguiWelcomeMessageTemplate"),
|
||||
-namespace => "Auth/WebGUI/Welcome",
|
||||
-label => $i18n->get("welcome message template"),
|
||||
-hoverHelp => $i18n->get("welcome message template help")
|
||||
);
|
||||
$f->template(
|
||||
-name => "webguiAccountActivationTemplate",
|
||||
-value => $self->session->setting->get("webguiAccountActivationTemplate"),
|
||||
-namespace => "Auth/WebGUI/Activation",
|
||||
-label => $i18n->get("account activation template"),
|
||||
-hoverHelp => $i18n->get("account activation template help")
|
||||
);
|
||||
return $f->printRowsOnly;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -625,6 +642,8 @@ sub editUserSettingsFormSave {
|
|||
$s->set("webguiExpiredPasswordTemplate", $f->process("webguiExpiredPasswordTemplate","template"));
|
||||
$s->set("webguiLoginTemplate", $f->process("webguiLoginTemplate","template"));
|
||||
$s->set("webguiPasswordRecoveryTemplate", $f->process("webguiPasswordRecoveryTemplate","template"));
|
||||
$s->set("webguiWelcomeMessageTemplate", $f->process("webguiWelcomeMessageTemplate","template"));
|
||||
$s->set("webguiAccountActivationTemplate", $f->process("webguiAccountActivationTemplate","template"));
|
||||
|
||||
if (@errors) {
|
||||
return \@errors;
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ sub getFolder {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getNamepsaceRoot ( )
|
||||
=head2 getNamespaceRoot ( )
|
||||
|
||||
Figures out what the cache root for this namespace should be. A class method.
|
||||
|
||||
|
|
|
|||
|
|
@ -88,6 +88,17 @@ sub handler {
|
|||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 formatXML ( content )
|
||||
|
||||
Escape XML entities, &, <, >, ' and ".
|
||||
|
||||
=head3 content
|
||||
|
||||
The content that will have XML entities escaped.
|
||||
|
||||
=cut
|
||||
|
||||
sub formatXML {
|
||||
my $content = shift;
|
||||
$content =~ s/&/&/g;
|
||||
|
|
|
|||
190
lib/WebGUI/Form/AdSpace.pm
Normal file
190
lib/WebGUI/Form/AdSpace.pm
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
package WebGUI::Form::AdSpace;
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2009 Plain Black Corporation.
|
||||
-------------------------------------------------------------------
|
||||
Please read the legal notices (docs/legal.txt) and the license
|
||||
(docs/license.txt) that came with this distribution before using
|
||||
this software.
|
||||
-------------------------------------------------------------------
|
||||
http://www.plainblack.com info@plainblack.com
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use base 'WebGUI::Form::SelectList';
|
||||
use WebGUI::International;
|
||||
use WebGUI::SQL;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Form::AdSpace
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Creates a group chooser field for AdSpace values.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
This is a subclass of WebGUI::Form::SelectList.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
The following methods are specifically available from this class. Check the superclass for additional methods.
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 areOptionsSettable ( )
|
||||
|
||||
Returns 0.
|
||||
|
||||
=cut
|
||||
|
||||
sub areOptionsSettable {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( [ additionalTerms ] )
|
||||
|
||||
See the super class for additional details.
|
||||
|
||||
=head3 additionalTerms
|
||||
|
||||
The following additional parameters have been added via this sub class.
|
||||
|
||||
=head4 size
|
||||
|
||||
How many rows should be displayed at once? Defaults to 1.
|
||||
|
||||
=head4 defaultValue
|
||||
|
||||
This will be used if no value is specified. Should be passed as an array reference. Defaults to 1.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift || [];
|
||||
push(@{$definition}, {
|
||||
size=>{
|
||||
defaultValue=>1
|
||||
},
|
||||
});
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getDatabaseFieldType ( )
|
||||
|
||||
Returns "CHAR(22) BINARY".
|
||||
|
||||
=cut
|
||||
|
||||
sub getDatabaseFieldType {
|
||||
return "CHAR(22) BINARY";
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getName ( session )
|
||||
|
||||
Returns the human readable name of this control.
|
||||
|
||||
=cut
|
||||
|
||||
sub getName {
|
||||
my ($self, $session) = @_;
|
||||
return WebGUI::International->new($session, 'WebGUI')->get('Ad Space control name');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getValueAsHtml ( )
|
||||
|
||||
Formats as a name.
|
||||
|
||||
=cut
|
||||
|
||||
sub getValueAsHtml {
|
||||
my $self = shift;
|
||||
my $item = WebGUI::AdSpace->new($self->session, $self->getOriginalValue);
|
||||
if (defined $item) {
|
||||
return $item->name;
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 isDynamicCompatible ( )
|
||||
|
||||
A class method that returns a boolean indicating whether this control is compatible with the DynamicField control.
|
||||
|
||||
=cut
|
||||
|
||||
sub isDynamicCompatible {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 toHtml ( )
|
||||
|
||||
Returns a group pull-down field. A group pull down provides a select list that provides name value pairs for all the groups in the WebGUI system.
|
||||
|
||||
=cut
|
||||
|
||||
sub toHtml {
|
||||
my $self = shift;
|
||||
my $options = { map { $_->getId => $_->get('name') } ( @{ WebGUI::AdSpace->getAdSpaces($self->session) } ) };
|
||||
$self->set('defaultValue', ( keys %{$options} )[0] );
|
||||
$self->set('options', $options );
|
||||
return $self->SUPER::toHtml();
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 toHtmlAsHidden ( )
|
||||
|
||||
Creates a series of hidden fields representing the data in the list.
|
||||
|
||||
=cut
|
||||
|
||||
sub toHtmlAsHidden {
|
||||
my $self = shift;
|
||||
my $options = { map { $_->getId => $_->get('name') } ( @{ WebGUI::AdSpace->getAdSpaces($self->session) } ) };
|
||||
$self->set('defaultValue', ( keys %{$options} )[0] );
|
||||
$self->set('options', $options );
|
||||
return $self->SUPER::toHtmlAsHidden();
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 toHtmlWithWrapper ( )
|
||||
|
||||
Renders the form field to HTML as a table row complete with labels, subtext, hoverhelp, etc. Also adds a manage icon next to the field if the current user is in the admins group.
|
||||
|
||||
=cut
|
||||
|
||||
sub toHtmlWithWrapper {
|
||||
my $self = shift;
|
||||
if ($self->session->user->isAdmin) {
|
||||
my $subtext = $self->session->icon->manage("op=manageAdSpaces");
|
||||
$self->set("subtext",$subtext . $self->get("subtext"));
|
||||
}
|
||||
return $self->SUPER::toHtmlWithWrapper;
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
|
|
@ -182,6 +182,12 @@ sub toHtml {
|
|||
return $self->SUPER::toHtml.'<p style="display:inline;vertical-align:middle;"><img src="'.$storage->getUrl($filename).'" style="border-style:none;vertical-align:middle;" alt="captcha" /></p>';
|
||||
}
|
||||
|
||||
=head2 getErrorMessage ( )
|
||||
|
||||
Returns an internationalized error message based on which kind of captcha is being used.
|
||||
|
||||
=cut
|
||||
|
||||
sub getErrorMessage {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ sub toHtml {
|
|||
my $output = "";
|
||||
|
||||
# Do our superclass's job
|
||||
my $value = $self->fixMacros($self->fixTags($self->fixSpecialCharacters($self->getOriginalValue)));
|
||||
my $value = $self->fixMacros($self->fixTags($self->fixSpecialCharacters(scalar $self->getOriginalValue)));
|
||||
my $width = $self->get('width') || 400;
|
||||
my $height = $self->get('height') || 150;
|
||||
my ($style, $url) = $self->session->quick(qw(style url));
|
||||
|
|
|
|||
|
|
@ -196,6 +196,9 @@ sub definition {
|
|||
idPrefix=>{
|
||||
defaultValue=>undef
|
||||
},
|
||||
allowEmpty=>{
|
||||
defaultValue => 0,
|
||||
},
|
||||
});
|
||||
return $definition;
|
||||
}
|
||||
|
|
@ -686,7 +689,7 @@ Renders the form field to HTML as a hidden field rather than whatever field type
|
|||
sub toHtmlAsHidden {
|
||||
my $self = shift;
|
||||
return '<input type="hidden" name="'.$self->get("name").'" value="'.
|
||||
$self->fixQuotes($self->fixMacros($self->fixSpecialCharacters($self->getOriginalValue()))).'" />'."\n";
|
||||
$self->fixQuotes($self->fixMacros($self->fixSpecialCharacters(scalar $self->getOriginalValue()))).'" />'."\n";
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
|
|||
173
lib/WebGUI/Form/Keywords.pm
Normal file
173
lib/WebGUI/Form/Keywords.pm
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
package WebGUI::Form::Keywords;
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2009 Plain Black Corporation.
|
||||
-------------------------------------------------------------------
|
||||
Please read the legal notices (docs/legal.txt) and the license
|
||||
(docs/license.txt) that came with this distribution before using
|
||||
this software.
|
||||
-------------------------------------------------------------------
|
||||
http://www.plainblack.com info@plainblack.com
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use base 'WebGUI::Form::Text';
|
||||
use WebGUI::International;
|
||||
use JSON ();
|
||||
use WebGUI::Keyword;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Form::Keywords
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Creates a keywords chooser field with multiple select and autocomplete.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
This is a subclass of WebGUI::Form::SelectList.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
The following methods are specifically available from this class. Check the superclass for additional methods.
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getDatabaseFieldType ( )
|
||||
|
||||
Returns "CHAR(22) BINARY".
|
||||
|
||||
=cut
|
||||
|
||||
sub getDatabaseFieldType {
|
||||
return "CHAR(255)";
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getName ( session )
|
||||
|
||||
Returns the human readable name of this control.
|
||||
|
||||
=cut
|
||||
|
||||
sub getName {
|
||||
my ($self, $session) = @_;
|
||||
return WebGUI::International->new($session, 'Asset')->get('keywords');
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 isDynamicCompatible ( )
|
||||
|
||||
A class method that returns a boolean indicating whether this control is compatible with the DynamicField control.
|
||||
|
||||
=cut
|
||||
|
||||
sub isDynamicCompatible {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 toHtml ( )
|
||||
|
||||
Returns a keyword pull-down field. A keyword pull down provides a select list that provides name value pairs for all the keywords in the WebGUI system.
|
||||
|
||||
=cut
|
||||
|
||||
sub toHtml {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $style = $session->style;
|
||||
my $url = $session->url;
|
||||
|
||||
$style->setLink($url->extras("yui/build/autocomplete/assets/skins/sam/autocomplete.css"), {rel=>"stylesheet", type=>"text/css"});
|
||||
$style->setScript($url->extras("yui/build/yahoo-dom-event/yahoo-dom-event.js"), {type=>"text/javascript"});
|
||||
$style->setScript($url->extras("yui/build/datasource/datasource-min.js"), {type=>"text/javascript"});
|
||||
$style->setScript($url->extras("yui/build/autocomplete/autocomplete-min.js"), {type=>"text/javascript"});
|
||||
$style->setRawHeadTags('<style type="text/css">.yui-skin-sam.webgui-keywords-autocomplete .yui-ac-input { position: static; width: auto }</style>');
|
||||
|
||||
my $name = $self->generateIdParameter($self->get('name'));
|
||||
my $autocompleteDiv = $self->privateName('autocomplete');
|
||||
my $pageUrl = $url->page;
|
||||
my $output
|
||||
= '<div class="yui-skin-sam webgui-keywords-autocomplete"><div>' . $self->SUPER::toHtml
|
||||
. '<div id="' . $autocompleteDiv . '"></div>'
|
||||
. '<script type="text/javascript">' . <<"END_SCRIPT" . '</script></div></div>';
|
||||
(function() {
|
||||
var oDS = new YAHOO.util.XHRDataSource('$pageUrl');
|
||||
oDS.responseType = YAHOO.util.XHRDataSource.TYPE_JSON;
|
||||
oDS.responseSchema = {
|
||||
resultsList : "keywords",
|
||||
};
|
||||
|
||||
var oAC = new YAHOO.widget.AutoComplete("$name", "$autocompleteDiv", oDS);
|
||||
oAC.queryDelay = 0.5;
|
||||
oAC.maxResultsDisplayed = 20;
|
||||
oAC.minQueryLength = 3;
|
||||
oAC.delimChar = [','];
|
||||
|
||||
oAC.generateRequest = function(sQuery) {
|
||||
return "?op=formHelper;class=Keywords;sub=searchAsJSON;search=" + sQuery ;
|
||||
};
|
||||
})();
|
||||
END_SCRIPT
|
||||
return $output;
|
||||
}
|
||||
|
||||
sub www_searchAsJSON {
|
||||
my $session = shift;
|
||||
my $search = $session->form->param('search');
|
||||
my $keyword = WebGUI::Keyword->new($session);
|
||||
|
||||
my $keywords = $keyword->findKeywords({search => $search, limit => 20});
|
||||
$session->http->setMimeType('application/json');
|
||||
|
||||
return JSON::to_json({keywords => $keywords});
|
||||
}
|
||||
|
||||
sub getDefaultValue {
|
||||
my $self = shift;
|
||||
return _formatKeywordsAsWanted($self->SUPER::getDefaultValue(@_));
|
||||
}
|
||||
|
||||
sub getOriginalValue {
|
||||
my $self = shift;
|
||||
return _formatKeywordsAsWanted($self->SUPER::getOriginalValue(@_));
|
||||
}
|
||||
|
||||
sub getValue {
|
||||
my $self = shift;
|
||||
return _formatKeywordsAsWanted($self->SUPER::getValue(@_));
|
||||
}
|
||||
|
||||
sub _formatKeywordsAsWanted {
|
||||
my @keywords;
|
||||
if (@_ == 1 && ref $_[0] eq 'ARRAY') {
|
||||
@keywords = @{ $_[0] };
|
||||
}
|
||||
else {
|
||||
for my $param (@_) {
|
||||
for my $keyword (split /,/, $param) {
|
||||
$keyword =~ s/^\s+//;
|
||||
$keyword =~ s/\s+$//;
|
||||
push @keywords, $keyword;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wantarray) {
|
||||
return @keywords;
|
||||
}
|
||||
return join(', ', @keywords);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
|
@ -220,7 +220,7 @@ sub getValue {
|
|||
@values = $self->session->form->param($self->get("name"));
|
||||
}
|
||||
}
|
||||
if (scalar @values < 1) {
|
||||
if (scalar @values < 1 && ! $self->get('allowEmpty')) {
|
||||
@values = $self->getDefaultValue;
|
||||
}
|
||||
return wantarray ? @values : join("\n",@values);
|
||||
|
|
@ -262,18 +262,17 @@ Returns the either the "value" ore "defaultValue" passed in to the object in tha
|
|||
sub getOriginalValue {
|
||||
my $self = shift;
|
||||
my @values = ();
|
||||
foreach my $value ($self->get("value")) {
|
||||
if (scalar @values < 1 && defined $value) {
|
||||
if (ref $value eq "ARRAY") {
|
||||
@values = @{$value};
|
||||
}
|
||||
else {
|
||||
$value =~ s/\r//g;
|
||||
@values = split "\n", $value;
|
||||
}
|
||||
my $value = $self->get("value");
|
||||
if (defined $value) {
|
||||
if (ref $value eq "ARRAY") {
|
||||
@values = @{$value};
|
||||
}
|
||||
else {
|
||||
$value =~ s/\r//g;
|
||||
@values = split "\n", $value;
|
||||
}
|
||||
}
|
||||
if (@values) {
|
||||
if (@values || ($self->get('allowEmpty') && defined $value) ) {
|
||||
return wantarray ? @values : join("\n",@values);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ sub isDynamicCompatible {
|
|||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 new
|
||||
=head2 getOptions
|
||||
|
||||
Create a new WebGUI::Form::SelectRichEditor object and populate it with all
|
||||
the available Rich Text Editor assets.
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ Renders the form field to HTML as a table row. The row is not displayed because
|
|||
|
||||
sub toHtmlWithWrapper {
|
||||
my $self = shift;
|
||||
my $value = $self->fixMacros($self->fixQuotes($self->fixSpecialCharacters($self->getOriginalValue))) || '';
|
||||
my $value = $self->fixMacros($self->fixQuotes($self->fixSpecialCharacters(scalar $self->getOriginalValue))) || '';
|
||||
if ($value) {
|
||||
my $manageButton = $self->session->icon->manage("op=editGroup;gid=".$value);
|
||||
$self->set("subtext",$manageButton . $self->get("subtext"));
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ Renders an input tag of type text.
|
|||
|
||||
sub toHtml {
|
||||
my $self = shift;
|
||||
my $value = $self->fixMacros($self->fixQuotes($self->fixSpecialCharacters($self->getOriginalValue)));
|
||||
my $value = $self->fixMacros($self->fixQuotes($self->fixSpecialCharacters(scalar $self->getOriginalValue)));
|
||||
return '<input id="'.$self->get('id').'" type="text" name="'.$self->get("name").'" value="'.$value.'" size="'.$self->get("size").'" maxlength="'.$self->get("maxlength").'" '.$self->get("extras").' />';
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ Renders an input tag of type text.
|
|||
|
||||
sub toHtml {
|
||||
my $self = shift;
|
||||
my $value = $self->fixMacros($self->fixTags($self->fixSpecialCharacters($self->getOriginalValue)));
|
||||
my $value = $self->fixMacros($self->fixTags($self->fixSpecialCharacters(scalar $self->getOriginalValue)));
|
||||
my $width = $self->get('width') || 400;
|
||||
my $height = $self->get('height') || 150;
|
||||
my ($style, $url) = $self->session->quick(qw(style url));
|
||||
|
|
@ -195,6 +195,14 @@ sub toHtml {
|
|||
return $out;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getValueAsHtml
|
||||
|
||||
Returns the form value as text, encoding HTML entities.
|
||||
|
||||
=cut
|
||||
|
||||
sub getValueAsHtml {
|
||||
my $self = shift;
|
||||
my $value = $self->SUPER::getValueAsHtml(@_);
|
||||
|
|
|
|||
|
|
@ -442,6 +442,18 @@ sub splitTag {
|
|||
return @result if wantarray;
|
||||
return $result[0];
|
||||
}
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 WebGUI::HTML::splitHeadBody($html);
|
||||
|
||||
splits an block of HTML into a HEAD and a BODY section
|
||||
|
||||
=head3 html
|
||||
|
||||
The block of HTML text that will be disected
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
sub splitHeadBody {
|
||||
my $html = shift;
|
||||
|
|
|
|||
29
lib/WebGUI/Help/Asset_Carousel.pm
Normal file
29
lib/WebGUI/Help/Asset_Carousel.pm
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package WebGUI::Help::Asset_Carousel;
|
||||
use strict;
|
||||
|
||||
our $HELP = {
|
||||
|
||||
'search template' => {
|
||||
title => 'carousel template help title',
|
||||
body => '',
|
||||
isa => [
|
||||
{ namespace => "Asset_Wobject",
|
||||
tag => "wobject template variables",
|
||||
},
|
||||
],
|
||||
variables => [
|
||||
{ 'name' => 'item_loop',
|
||||
'variables' => [
|
||||
{ 'name' => 'text' },
|
||||
{ 'name' => 'itemId'},
|
||||
{ 'name' => 'sequenceNumber'},
|
||||
],
|
||||
}
|
||||
],
|
||||
related => [],
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ our $HELP = {
|
|||
{ 'name' => 'page.isChild' },
|
||||
{ 'name' => 'page.isParent' },
|
||||
{ 'name' => 'page.isCurrent' },
|
||||
{ 'name' => 'page.isDescendent' },
|
||||
{ 'name' => 'page.isDescendant' },
|
||||
{ 'name' => 'page.isAncestor' },
|
||||
{ 'name' => 'page.inBranchRoot' },
|
||||
{ 'name' => 'page.isSibling' },
|
||||
|
|
|
|||
|
|
@ -136,11 +136,7 @@ our $HELP = {
|
|||
private => 1,
|
||||
title => 'post asset variables title',
|
||||
body => '',
|
||||
isa => [
|
||||
{ tag => 'asset template asset variables',
|
||||
namespace => 'Asset'
|
||||
},
|
||||
],
|
||||
isa => [ ],
|
||||
variables => [
|
||||
{ 'name' => 'storageId' },
|
||||
{ 'name' => 'threadId' },
|
||||
|
|
|
|||
|
|
@ -1,53 +0,0 @@
|
|||
package WebGUI::Help::Asset_RSSFromParent;
|
||||
use strict;
|
||||
|
||||
our $HELP = {
|
||||
'rss from parent' => {
|
||||
title => 'rss from parent title',
|
||||
body => 'rss from parent body',
|
||||
|
||||
# use the following to inherit stuff other help entries
|
||||
isa => [
|
||||
{ tag => 'template variables',
|
||||
namespace => 'Asset_Template'
|
||||
},
|
||||
],
|
||||
fields => [ #This array is used to list hover help for form fields.
|
||||
],
|
||||
variables => [
|
||||
{ 'name' => 'title',
|
||||
'description' => 'title.parent'
|
||||
},
|
||||
{ 'name' => 'link',
|
||||
'description' => 'title.parent'
|
||||
},
|
||||
{ 'name' => 'description',
|
||||
'description' => 'description.parent'
|
||||
},
|
||||
{ 'name' => 'generator' },
|
||||
{ 'name' => 'lastBuildDate' },
|
||||
{ 'name' => 'webMaster' },
|
||||
{ 'name' => 'docs' },
|
||||
{ 'name' => 'item_loop',
|
||||
variables => [
|
||||
{ 'name' => 'title',
|
||||
'description' => 'title.item'
|
||||
},
|
||||
{ 'name' => 'link',
|
||||
'description' => 'title.item'
|
||||
},
|
||||
{ 'name' => 'description',
|
||||
'description' => 'description.item'
|
||||
},
|
||||
{ 'name' => 'guid' },
|
||||
{ 'name' => 'pubDate' },
|
||||
]
|
||||
},
|
||||
],
|
||||
related => [ ##This lists other help articles that are related to this one
|
||||
],
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1; ##All perl modules must return true
|
||||
|
|
@ -21,8 +21,11 @@ our $HELP = {
|
|||
variables => [
|
||||
{ name => "shelves" , required=>1},
|
||||
{ name => "products" , required=>1, variables => [
|
||||
{ name => "url",
|
||||
description => 'product_url', },
|
||||
{ name => "thumbnailUrl" },
|
||||
{ name => "price" },
|
||||
{ name => "addToCartForm" },
|
||||
],
|
||||
},
|
||||
{ name => "templateId", description=>"shelf template help" },
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ our $HELP = {
|
|||
{ 'name' => 'thing_deleteUrl' },
|
||||
{ 'name' => 'thing_searchUrl' },
|
||||
{ 'name' => 'thing_addUrl' },
|
||||
{ 'name' => 'thing_copyUrl' },
|
||||
{ 'name' => 'thing_copyIcon' },
|
||||
]
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -163,6 +163,28 @@ our $HELP = {
|
|||
related => [],
|
||||
},
|
||||
|
||||
'webgui welcome message template' => {
|
||||
title => 'welcome message template title',
|
||||
body => '',
|
||||
variables => [
|
||||
{ 'name' => 'welcomeMessage' },
|
||||
{ 'name' => 'newUser_username' },
|
||||
{ 'name' => 'newUser_password' },
|
||||
],
|
||||
fields => [],
|
||||
related => []
|
||||
},
|
||||
|
||||
'account activation template' => {
|
||||
title => 'account activation template title',
|
||||
body => '',
|
||||
variables => [
|
||||
{ 'name' => 'newUser_username' },
|
||||
{ 'name' => 'activationUrl' },
|
||||
],
|
||||
fields => [],
|
||||
related => []
|
||||
},
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -163,14 +163,9 @@ sub create {
|
|||
$preface = sprintf($i18n->get('from user preface'), $fromUser->username);
|
||||
}
|
||||
my $msg = (defined $properties->{emailMessage}) ? $properties->{emailMessage} : $self->{_properties}{message};
|
||||
if ($msg =~ m/\<.*\>/) {
|
||||
$msg = '<p>' . $preface . '</p><br />'.$msg if($preface ne "");
|
||||
$mail->addHtml($msg);
|
||||
} else {
|
||||
$msg = $preface."\n\n".$msg if($preface ne "");
|
||||
$mail->addText($msg);
|
||||
}
|
||||
$mail->addFooter;
|
||||
$msg = '<p>' . $preface . '</p><br />'.$msg if($preface ne "");
|
||||
$mail->addHtml($msg);
|
||||
$mail->addFooter;
|
||||
$mail->queue;
|
||||
}
|
||||
$self->{_session} = $session;
|
||||
|
|
|
|||
|
|
@ -88,6 +88,67 @@ sub deleteKeyword {
|
|||
$self->session->db->write("delete from assetKeyword where keyword=?", [$options->{keyword}]);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 findKeywords ( $options )
|
||||
|
||||
Find keywords.
|
||||
|
||||
=head3 $options
|
||||
|
||||
A hashref of options to change the behavior of the method.
|
||||
|
||||
=head4 asset
|
||||
|
||||
Find all keywords for all assets below an asset, providing a WebGUI::Asset object.
|
||||
|
||||
=head4 assetId
|
||||
|
||||
Find all keywords for all assets below an asset, providing an assetId.
|
||||
|
||||
=head4 search
|
||||
|
||||
Find all keywords using the SQL clause LIKE. This can be used in tandem with asset or assetId.
|
||||
|
||||
=head4 limit
|
||||
|
||||
Limit the number of keywords that are returned.
|
||||
|
||||
=cut
|
||||
|
||||
sub findKeywords {
|
||||
my $self = shift;
|
||||
my $options = shift;
|
||||
|
||||
my $sql = 'SELECT keyword FROM assetKeyword';
|
||||
my @where;
|
||||
my @placeholders;
|
||||
my $parentAsset;
|
||||
if ($options->{asset}) {
|
||||
$parentAsset = $options->{asset};
|
||||
}
|
||||
if ($options->{assetId}) {
|
||||
$parentAsset = WebGUI::Asset->new($self->session, $options->{assetId});
|
||||
}
|
||||
if ($parentAsset) {
|
||||
$sql .= ' INNER JOIN asset USING (assetId)';
|
||||
push @where, 'lineage LIKE ?';
|
||||
push @placeholders, $parentAsset->get('lineage') . '%';
|
||||
}
|
||||
if ($options->{search}) {
|
||||
push @where, 'keyword LIKE ?';
|
||||
push @placeholders, '%' . $options->{search} . '%';
|
||||
}
|
||||
if (@where) {
|
||||
$sql .= ' WHERE ' . join(' AND ', @where);
|
||||
}
|
||||
$sql .= ' GROUP BY keyword';
|
||||
if ($options->{limit}) {
|
||||
$sql .= ' LIMIT ' . $options->{limit};
|
||||
}
|
||||
my $keywords = $self->session->db->buildArrayRef($sql, \@placeholders);
|
||||
return $keywords;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -123,14 +184,32 @@ sub generateCloud {
|
|||
my $self = shift;
|
||||
my $options = shift;
|
||||
my $display = $options->{displayAsset} || $options->{startAsset};
|
||||
my $sth = $self->session->db->read("select count(*) as keywordTotal, keyword from assetKeyword
|
||||
left join asset using (assetId) where lineage like ? group by keyword order by keywordTotal desc limit 50",
|
||||
[ $options->{startAsset}->get("lineage").'%' ]);
|
||||
my $includeKeywords = $options->{includeOnlyKeywords};
|
||||
my $maxKeywords = $options->{maxKeywords} || 50;
|
||||
if ($maxKeywords > 100) {
|
||||
$maxKeywords = 100;
|
||||
}
|
||||
my $urlCallback = $options->{urlCallback};
|
||||
my $extraWhere = '';
|
||||
my @extraPlaceholders;
|
||||
if ($includeKeywords) {
|
||||
$extraWhere .= ' AND keyword IN (' . join(',', ('?') x @{$includeKeywords}) . ')';
|
||||
push @extraPlaceholders, @{$includeKeywords};
|
||||
}
|
||||
my $sth = $self->session->db->read("SELECT COUNT(*) as keywordTotal, keyword FROM assetKeyword
|
||||
LEFT JOIN asset USING (assetId) WHERE lineage LIKE ? $extraWhere
|
||||
GROUP BY keyword ORDER BY keywordTotal DESC LIMIT ?",
|
||||
[ $options->{startAsset}->get("lineage").'%', @extraPlaceholders, $maxKeywords ]);
|
||||
my $cloud = HTML::TagCloud->new(levels=>$options->{cloudLevels} || 24);
|
||||
while (my ($count, $keyword) = $sth->array) {
|
||||
$cloud->add($keyword, $display->getUrl("func=".$options->{displayFunc}.";keyword=".$keyword), $count);
|
||||
my $url
|
||||
= $urlCallback ? $display->$urlCallback($keyword)
|
||||
: $options->{displayFunc} ? $display->getUrl("func=".$options->{displayFunc}.";keyword=".$keyword)
|
||||
: $display->getUrl("keyword=".$keyword)
|
||||
;
|
||||
$cloud->add($keyword, $url, $count);
|
||||
}
|
||||
return $cloud->html_and_css($options->{maxKeywords});
|
||||
return $cloud->html_and_css($maxKeywords);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -152,13 +231,14 @@ A boolean, that if set to 1 will return the keywords as an array reference rathe
|
|||
|
||||
sub getKeywordsForAsset {
|
||||
my ($self, $options) = @_;
|
||||
my @keywords = $self->session->db->buildArray("select keyword from assetKeyword where assetId=?",
|
||||
[$options->{asset}->getId]);
|
||||
my $assetId = $options->{asset} ? $options->{asset}->getId : $options->{assetId};
|
||||
my $keywords = $self->session->db->buildArrayRef("select keyword from assetKeyword where assetId=?",
|
||||
[$assetId]);
|
||||
if ($options->{asArrayRef}) {
|
||||
return \@keywords;
|
||||
return $keywords;
|
||||
}
|
||||
else {
|
||||
return join(" ", map({ (m/\s/) ? '"' . $_ . '"' : $_ } @keywords));
|
||||
return join(', ', @$keywords);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -321,9 +401,9 @@ Either a string of space-separated keywords, or an array reference of keywords t
|
|||
sub setKeywordsForAsset {
|
||||
my $self = shift;
|
||||
my $options = shift;
|
||||
my $keywords = [];
|
||||
my $keywords;
|
||||
if (ref $options->{keywords} eq "ARRAY") {
|
||||
$keywords = $options->{keywords};
|
||||
$keywords = $options->{keywords};
|
||||
}
|
||||
else {
|
||||
$keywords = string2list($options->{keywords});
|
||||
|
|
@ -339,7 +419,7 @@ sub setKeywordsForAsset {
|
|||
next
|
||||
if $found_keywords{$keyword};
|
||||
$found_keywords{$keyword}++;
|
||||
$sth->execute([$assetId, lc($keyword)]);
|
||||
$sth->execute([$assetId, $keyword]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -352,35 +432,18 @@ Returns an array reference of phrases.
|
|||
|
||||
=head3 string
|
||||
|
||||
A scalar containing space separated phrases.
|
||||
A scalar containing comma separated phrases.
|
||||
|
||||
=cut
|
||||
|
||||
sub string2list {
|
||||
my $text = shift;
|
||||
return if (ref $text);
|
||||
my @words = ();
|
||||
my $word = '';
|
||||
my $errorFlag = 0;
|
||||
while ( defined $text and length $text and not $errorFlag) {
|
||||
if ($text =~ s/\A(?: ([^\"\s\\]+) | \\(.) )//mx) {
|
||||
$word .= $1;
|
||||
}
|
||||
elsif ($text =~ s/\A"((?:[^\"\\]|\\.)*)"//mx) {
|
||||
$word .= $1;
|
||||
}
|
||||
elsif ($text =~ s/\A\s+//m){
|
||||
push(@words, $word);
|
||||
$word = '';
|
||||
}
|
||||
elsif ($text =~ s/\A"//) {
|
||||
$errorFlag = 1;
|
||||
}
|
||||
else {
|
||||
$errorFlag = 1;
|
||||
}
|
||||
my @words = split /,/, $text;
|
||||
for my $word (@words) {
|
||||
$word =~ s/^\s+//;
|
||||
$word =~ s/\s+$//;
|
||||
}
|
||||
push(@words, $word);
|
||||
return \@words;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ sub www_switchOffAdmin {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_adminConsole ( )
|
||||
=head2 www_switchOnAdmin ( )
|
||||
|
||||
If the current user is in the Turn On Admin Group, then allow them to turn on Admin mode.
|
||||
|
||||
|
|
|
|||
|
|
@ -451,6 +451,17 @@ sub www_commitVersionTagConfirm {
|
|||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_leaveVersionTag ( session )
|
||||
|
||||
Clears the current working version tag, and returns the user to www_manageVersions.
|
||||
|
||||
=head3 session
|
||||
|
||||
A reference to the current session.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_leaveVersionTag {
|
||||
my $session = shift;
|
||||
WebGUI::VersionTag->getWorking($session)->clearWorking;
|
||||
|
|
|
|||
|
|
@ -173,8 +173,11 @@ returns true is the client/agent is a spider/indexer or some other non-human int
|
|||
sub requestNotViewed {
|
||||
|
||||
my $self = shift;
|
||||
return $self->clientIsSpider()
|
||||
|| $self->callerIsSearchSite();
|
||||
return $self->clientIsSpider();
|
||||
# || $self->callerIsSearchSite(); # this part is currently left out because
|
||||
# it has minimal effect and does not manage
|
||||
# IPv6 addresses. it may be useful in the
|
||||
# future though
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,16 +87,25 @@ sub DESTROY {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 get ( )
|
||||
=head2 get ( $param )
|
||||
|
||||
Returns a hash reference containing all the settings.
|
||||
|
||||
=head3 $param
|
||||
|
||||
If $param is defined, then it will return only the setting for that param.
|
||||
|
||||
=cut
|
||||
|
||||
sub get {
|
||||
my $self = shift;
|
||||
my $param = shift;
|
||||
return $self->{_settings}{$param};
|
||||
my $self = shift;
|
||||
my $param = shift;
|
||||
if (defined $param) {
|
||||
return $self->{_settings}{$param};
|
||||
}
|
||||
else {
|
||||
return $self->{_settings};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -152,6 +152,13 @@ sub www_editSettings {
|
|||
label => $i18n->get('who is a cashier'),
|
||||
hoverHelp => $i18n->get('who is a cashier help'),
|
||||
);
|
||||
$form->float(
|
||||
name => 'shopCartCheckoutMinimum',
|
||||
value => $setting->get('shopCartCheckoutMinimum'),
|
||||
defaultValue=> '0.00',
|
||||
label => $i18n->get('cart checkout minimum'),
|
||||
hoverHelp => $i18n->get('cart checkout minimum help'),
|
||||
);
|
||||
$form->template(
|
||||
name => "shopCartTemplateId",
|
||||
value => $setting->get("shopCartTemplateId"),
|
||||
|
|
@ -203,13 +210,21 @@ sub www_editSettingsSave {
|
|||
my $self = shift;
|
||||
return $self->session->privilege->adminOnly() unless ($self->session->user->isAdmin);
|
||||
my ($setting, $form) = $self->session->quick(qw(setting form));
|
||||
|
||||
# Save shop templates
|
||||
foreach my $template (qw(shopMyPurchasesDetailTemplateId shopMyPurchasesTemplateId
|
||||
shopCartTemplateId shopAddressBookTemplateId shopAddressTemplateId)) {
|
||||
$setting->set($template, $form->get($template, "template"));
|
||||
}
|
||||
|
||||
# Save group settings
|
||||
foreach my $group (qw(groupIdCashier groupIdAdminCommerce)) {
|
||||
$setting->set($group, $form->get($group, "group"));
|
||||
}
|
||||
|
||||
# Save mininmum cart checkout
|
||||
$setting->set( 'shopCartCheckoutMinimum', $form->get( 'shopCartCheckoutMinimum', 'float' ) );
|
||||
|
||||
return $self->www_editSettings();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ sub create {
|
|||
WebGUI::Error::InvalidObject->throw(expected=>"WebGUI::Session", got=>(ref $session), error=>"Need a session.");
|
||||
}
|
||||
my $cartId = $session->id->generate;
|
||||
$session->db->write('insert into cart (cartId, sessionId) values (?,?)', [$cartId, $session->getId]);
|
||||
$session->db->write('insert into cart (cartId, sessionId, creationDate) values (?,?,UNIX_TIMESTAMP())', [$cartId, $session->getId]);
|
||||
return $class->new($session, $cartId);
|
||||
}
|
||||
|
||||
|
|
@ -498,21 +498,23 @@ Returns whether all the required properties of the the cart are set.
|
|||
|
||||
sub readyForCheckout {
|
||||
my $self = shift;
|
||||
|
||||
|
||||
# Check if the shipping address is set and correct
|
||||
my $address = eval{$self->getShippingAddress};
|
||||
return 0 if WebGUI::Error->caught;
|
||||
|
||||
# Check if the ship driver is chosen and existant
|
||||
my $ship = eval {$self->getShipper};
|
||||
return 0 if WebGUI::Error->caught;
|
||||
|
||||
# Check if the cart has items
|
||||
return 0 unless scalar @{ $self->getItems };
|
||||
|
||||
# fail if there are multiple recurring items or if
|
||||
return 0 if ($self->hasMixedItems);
|
||||
|
||||
# Check minimum cart checkout requirement
|
||||
my $requiredAmount = $self->session->setting->get( 'shopCartCheckoutMinimum' );
|
||||
if ( $requiredAmount > 0 ) {
|
||||
return 0 if $self->calculateTotal < $requiredAmount;
|
||||
}
|
||||
|
||||
# All checks passed so return true
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -559,6 +561,10 @@ The unique id of the configured shipping driver that will be used to ship these
|
|||
|
||||
The ID of a user being checked out, if they're being checked out by a cashier.
|
||||
|
||||
=head4 creationDate
|
||||
|
||||
The date the cart was created.
|
||||
|
||||
=cut
|
||||
|
||||
sub update {
|
||||
|
|
@ -567,7 +573,7 @@ sub update {
|
|||
WebGUI::Error::InvalidParam->throw(error=>"Need a properties hash ref.");
|
||||
}
|
||||
my $id = id $self;
|
||||
foreach my $field (qw(shippingAddressId posUserId shipperId)) {
|
||||
foreach my $field (qw(shippingAddressId posUserId shipperId creationDate)) {
|
||||
$properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field};
|
||||
}
|
||||
$self->session->db->setRow("cart","cartId",$properties{$id});
|
||||
|
|
@ -801,6 +807,10 @@ sub www_view {
|
|||
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
|
||||
|
|
@ -846,10 +856,11 @@ sub www_view {
|
|||
# calculate price adjusted for in-store credit
|
||||
$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{ inShopCreditAvailable } = $credit->getSum;
|
||||
$var{ inShopCreditDeduction } = $credit->calculateDeduction($var{totalPrice});
|
||||
$var{ totalPrice } = $self->formatCurrency($var{totalPrice} + $var{inShopCreditDeduction});
|
||||
$var{ readyForCheckout } = $self->readyForCheckout;
|
||||
|
||||
# render the cart
|
||||
my $template = WebGUI::Asset::Template->new($session, $session->setting->get("shopCartTemplateId"));
|
||||
return $session->style->userStyle($template->process(\%var));
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ sub getSku {
|
|||
my ($self) = @_;
|
||||
my $asset = '';
|
||||
$asset = WebGUI::Asset->newByDynamicClass($self->cart->session, $self->get("assetId"));
|
||||
$asset->applyOptions($self->get("options"));
|
||||
$asset->applyOptions($self->get("options")) if $asset;
|
||||
return $asset;
|
||||
}
|
||||
|
||||
|
|
@ -229,7 +229,8 @@ Removes this item from the cart and calls $sku->onRemoveFromCart. See also delet
|
|||
|
||||
sub remove {
|
||||
my $self = shift;
|
||||
$self->getSku->onRemoveFromCart($self);
|
||||
my $sku = $self->getSku;
|
||||
$sku->onRemoveFromCart($self) if $sku;
|
||||
return $self->delete;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -226,6 +226,18 @@ Returns a reference to the current session.
|
|||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_addPaymentGateway ( $session )
|
||||
|
||||
Add a new payment gateway, based on the className form variable. It will throw
|
||||
an error, WebGUI::Error::InvalidParram if no className is passed.
|
||||
|
||||
=head3 $session
|
||||
|
||||
A reference to the current session object.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_addPaymentGateway {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use base qw/WebGUI::Shop::PayDriver/;
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 canCheckOutCart ( )
|
||||
=head2 canCheckoutCart ( )
|
||||
|
||||
Returns whether the cart can be checked out by this plugin.
|
||||
|
||||
|
|
@ -85,12 +85,6 @@ sub processPayment {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
sub www_displayStatus {
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_getCredentials ( [ addressId ] )
|
||||
|
||||
Displays the checkout form for this plugin.
|
||||
|
|
|
|||
|
|
@ -119,6 +119,48 @@ sub getId {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getPayoutTotals ( )
|
||||
|
||||
Returns a hash ref, containing the payout details for this vendor. The keys in the hash are:
|
||||
|
||||
=head3 paid
|
||||
|
||||
The amount of money already transfered to the vendor.
|
||||
|
||||
=head3 scheduled
|
||||
|
||||
The amount of money scheduled to be transfered to the vendor.
|
||||
|
||||
=head3 notPaid
|
||||
|
||||
The amount of money that is yet to be scheduled for payment to the vendor.
|
||||
|
||||
=head3 total
|
||||
|
||||
The sum of these three values.
|
||||
|
||||
=cut
|
||||
|
||||
sub getPayoutTotals {
|
||||
my $self = shift;
|
||||
|
||||
my %totals = $self->session->db->buildHash(
|
||||
'select vendorPayoutStatus, sum(vendorPayoutAmount) as amount from transactionItem '
|
||||
.'where vendorId=? group by vendorPayoutStatus ',
|
||||
[ $self->getId ]
|
||||
);
|
||||
|
||||
# Format the payout categories and calc the total those.
|
||||
%totals =
|
||||
map { lcfirst $_ => sprintf '%.2f', $totals{ $_ } }
|
||||
qw( Paid Scheduled NotPaid );
|
||||
$totals{ total } = sprintf '%.2f', sum values %totals;
|
||||
|
||||
return \%totals;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getVendors ( session, options )
|
||||
|
||||
Class method. Returns an array reference of WebGUI::Shop::Vendor objects.
|
||||
|
|
@ -152,6 +194,26 @@ sub getVendors {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 isVendorInfoComplete ( )
|
||||
|
||||
Returns a boolean indicating whether the payoutinformation entered by the vendor is complete.
|
||||
|
||||
=cut
|
||||
|
||||
sub isVendorInfoComplete {
|
||||
my $self = shift;
|
||||
|
||||
my $complete =
|
||||
defined $self->get( 'name' )
|
||||
&& defined $self->get( 'userId' )
|
||||
&& defined $self->get( 'preferredPaymentType' )
|
||||
&& defined $self->get( 'paymentInformation' );
|
||||
|
||||
return $complete
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 new ( session, vendorId )
|
||||
|
||||
Constructor. Returns a WebGUI::Shop::Vendor object.
|
||||
|
|
@ -407,47 +469,144 @@ sub www_manage {
|
|||
return $console->render($output, $i18n->get("vendors"));
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getPayoutTotals ( )
|
||||
=head2 www_managePayouts ( )
|
||||
|
||||
Returns a hash ref, containing the payout details for this vendor. The keys in the hash are:
|
||||
|
||||
=head3 paid
|
||||
|
||||
The amount of money already transfered to the vendor.
|
||||
|
||||
=head3 scheduled
|
||||
|
||||
The amount of money scheduled to be transfered to the vendor.
|
||||
|
||||
=head3 notPaid
|
||||
|
||||
The amount of money that is yet to be scheduled for payment to the vendor.
|
||||
|
||||
=head3 total
|
||||
|
||||
The sum of these three values.
|
||||
Displays the payout manager.
|
||||
|
||||
=cut
|
||||
|
||||
sub getPayoutTotals {
|
||||
my $self = shift;
|
||||
sub www_managePayouts {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
|
||||
my %totals = $self->session->db->buildHash(
|
||||
'select vendorPayoutStatus, sum(vendorPayoutAmount) as amount from transactionItem '
|
||||
.'where vendorId=? group by vendorPayoutStatus ',
|
||||
[ $self->getId ]
|
||||
);
|
||||
my $admin = WebGUI::Shop::Admin->new($session);
|
||||
return $session->privilege->adminOnly() unless ($admin->canManage);
|
||||
|
||||
# Load the required YUI stuff.
|
||||
my $style = $session->style;
|
||||
my $url = $session->url;
|
||||
|
||||
# Format the payout categories and calc the total those.
|
||||
%totals =
|
||||
map { lcfirst $_ => sprintf '%.2f', $totals{ $_ } }
|
||||
qw( Paid Scheduled NotPaid );
|
||||
$totals{ total } = sprintf '%.2f', sum values %totals;
|
||||
$style->setLink($url->extras('yui/build/paginator/assets/skins/sam/paginator.css'), {type=>'text/css', rel=>'stylesheet'});
|
||||
$style->setLink($url->extras('yui/build/datatable/assets/skins/sam/datatable.css'), {type=>'text/css', rel=>'stylesheet'});
|
||||
$style->setLink($url->extras('yui/build/button/assets/skins/sam/button.css'), {type=>'text/css', rel=>'stylesheet'});
|
||||
|
||||
return \%totals;
|
||||
$style->setScript($url->extras('yui/build/yahoo-dom-event/yahoo-dom-event.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/element/element-beta-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/connection/connection-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/json/json-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/paginator/paginator-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/datasource/datasource.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/datatable/datatable-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('yui/build/button/button-min.js'), {type=>'text/javascript'});
|
||||
$style->setScript($url->extras('VendorPayout/vendorPayout.js'), {type=>'text/javascript'});
|
||||
|
||||
# Add css for scheduled payout highlighting
|
||||
$style->setRawHeadTags(<<CSS);
|
||||
<style type="text/css">
|
||||
.yui-skin-sam .yui-dt tr.scheduled,
|
||||
.yui-skin-sam .yui-dt tr.scheduled td.yui-dt-asc,
|
||||
.yui-skin-sam .yui-dt tr.scheduled td.yui-dt-desc,
|
||||
.yui-skin-sam .yui-dt tr.scheduled td.yui-dt-asc,
|
||||
.yui-skin-sam .yui-dt tr.scheduled td.yui-dt-desc {
|
||||
background-color : #080;
|
||||
color : #fff;
|
||||
}
|
||||
</style>
|
||||
CSS
|
||||
|
||||
my $output = q{<div id="vendorPayoutContainer" class="yui-skin-sam"></div>}
|
||||
.q{<script type="text/javascript">var vp = new WebGUI.VendorPayout( 'vendorPayoutContainer' );</script>};
|
||||
|
||||
my $console = WebGUI::Shop::Admin->new($session)->getAdminConsole;
|
||||
my $i18n = WebGUI::International->new($session, 'Shop');
|
||||
return $console->render($output, $i18n->get('vendor payouts'));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_payoutDataAsJSON ( )
|
||||
|
||||
Returns a JSON string containing paginated payout data for a specific vendor.
|
||||
The following form params should be passed:
|
||||
|
||||
=head3 vendorId
|
||||
|
||||
The vendorId of the vendor you want the payout data for.
|
||||
|
||||
=head3 results
|
||||
|
||||
The number of results to be returned. Defaults to 100.
|
||||
|
||||
=head3 startIndex
|
||||
|
||||
The index of the record at which the payout data should start.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_payoutDataAsJSON {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
|
||||
my $admin = WebGUI::Shop::Admin->new($session);
|
||||
return $session->privilege->adminOnly() unless ($admin->canManage);
|
||||
|
||||
my $vendorId = $session->form->process('vendorId');
|
||||
my $startIndex = $session->form->process('startIndex');
|
||||
my $rowsPerPage = $session->form->process('results') || 100;
|
||||
my $pageNumber = int( $startIndex / $rowsPerPage ) + 1;
|
||||
|
||||
my $sql =
|
||||
"select t1.* from transactionItem as t1 join transaction as t2 on t1.transactionId=t2.transactionId "
|
||||
." where vendorId=? and vendorPayoutAmount > 0 and vendorPayoutStatus <> 'Paid' order by t2.orderNumber";
|
||||
my $placeholders = [ $vendorId ];
|
||||
|
||||
my $paginator = WebGUI::Paginator->new( $session, '', $rowsPerPage, '', $pageNumber );
|
||||
$paginator->setDataByQuery( $sql, undef, 0, $placeholders );
|
||||
|
||||
my $data = {
|
||||
totalRecords => $paginator->getRowCount,
|
||||
results => $paginator->getPageData,
|
||||
};
|
||||
|
||||
$session->http->setMimeType( 'application/json' );
|
||||
|
||||
return JSON::to_json( $data );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_setPayoutStatus ( )
|
||||
|
||||
Sets the vendorPayoutStatus flag for each transaction passed by the form param 'itemId'. The new status is passed
|
||||
by the form param 'status'. Status can either be 'NotPaid' or 'Scheduled' and may only be applied on items that do
|
||||
not have their vendorPayoutStatus set to 'Paid'.
|
||||
|
||||
Returns the status to which the item(s) are set.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_setPayoutStatus {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
|
||||
my $admin = WebGUI::Shop::Admin->new($session);
|
||||
return $session->privilege->adminOnly() unless ($admin->canManage);
|
||||
|
||||
my @itemIds = $session->form->process('itemId');
|
||||
my $status = $session->form->process('status');
|
||||
return "error: wrong status [$status]" unless isIn( $status, qw{ NotPaid Scheduled } );
|
||||
|
||||
foreach my $itemId (@itemIds) {
|
||||
my $item = WebGUI::Shop::TransactionItem->newByDynamicTransaction( $session, $itemId );
|
||||
return "error: invalid transactionItemId [$itemId]" unless $item;
|
||||
return "error: cannot change status of a Paid item" if $item->get('vendorPayoutStatus') eq 'Paid';
|
||||
|
||||
$item->update({ vendorPayoutStatus => $status });
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -477,43 +636,14 @@ sub www_submitScheduledPayouts {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_setPayoutStatus ( )
|
||||
|
||||
Sets the vendorPayoutStatus flag for each transaction passed by the form param 'itemId'. The new status is passed
|
||||
by the form param 'status'. Status can either be 'NotPaid' or 'Scheduled' and may only be applied on items that do
|
||||
not have their vendorPayoutStatus set to 'Paid'.
|
||||
|
||||
Returns the status to which the item(s) are set.
|
||||
=cut
|
||||
|
||||
sub www_setPayoutStatus {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
|
||||
my $admin = WebGUI::Shop::Admin->new($session);
|
||||
return $session->privilege->adminOnly() unless ($admin->canManage);
|
||||
|
||||
my @itemIds = $session->form->process('itemId');
|
||||
my $status = $session->form->process('status');
|
||||
return "error: wrong status [$status]" unless isIn( $status, qw{ NotPaid Scheduled } );
|
||||
|
||||
foreach my $itemId (@itemIds) {
|
||||
my $item = WebGUI::Shop::TransactionItem->newByDynamicTransaction( $session, $itemId );
|
||||
return "error: invalid transactionItemId [$itemId]" unless $item;
|
||||
return "error: cannot change status of a Paid item" if $item->get('vendorPayoutStatus') eq 'Paid';
|
||||
|
||||
$item->update({ vendorPayoutStatus => $status });
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_vendorTotalsAsJSON ( )
|
||||
|
||||
Returns a JSON string containing all vendors and their payout details. If a vendor id is passed through form param
|
||||
'vendorId' only results for that vendor will be returned.
|
||||
Returns a JSON string containing all vendors and their payout details. The following
|
||||
form parameters can be passed:
|
||||
|
||||
=head3 vendorId
|
||||
|
||||
If passed, the results will include only the totals of this vendor.
|
||||
|
||||
=cut
|
||||
|
||||
|
|
@ -555,78 +685,5 @@ sub www_vendorTotalsAsJSON {
|
|||
return JSON::to_json( { vendors => \@dataset } );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_payoutDataAsJSON {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
|
||||
my $admin = WebGUI::Shop::Admin->new($session);
|
||||
return $session->privilege->adminOnly() unless ($admin->canManage);
|
||||
|
||||
my $vendorId = $session->form->process('vendorId');
|
||||
my $startIndex = $session->form->process('startIndex');
|
||||
my $rowsPerPage = $session->form->process('results') || 100;
|
||||
my $pageNumber = int( $startIndex / $rowsPerPage ) + 1;
|
||||
|
||||
my $sql =
|
||||
"select t1.* from transactionItem as t1 join transaction as t2 on t1.transactionId=t2.transactionId "
|
||||
." where vendorId=? and vendorPayoutAmount > 0 and vendorPayoutStatus <> 'Paid' order by t2.orderNumber";
|
||||
my $placeholders = [ $vendorId ];
|
||||
|
||||
my $paginator = WebGUI::Paginator->new( $session, '', $rowsPerPage, '', $pageNumber );
|
||||
$paginator->setDataByQuery( $sql, undef, 0, $placeholders );
|
||||
|
||||
my $data = {
|
||||
totalRecords => $paginator->getRowCount,
|
||||
results => $paginator->getPageData,
|
||||
};
|
||||
|
||||
$session->http->setMimeType( 'application/json' );
|
||||
|
||||
return JSON::to_json( $data );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub www_managePayouts {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
|
||||
my $admin = WebGUI::Shop::Admin->new($session);
|
||||
return $session->privilege->adminOnly() unless ($admin->canManage);
|
||||
|
||||
# Load the required YUI stuff.
|
||||
$session->style->setLink('/extras/yui/build/paginator/assets/skins/sam/paginator.css', {type=>'text/css', rel=>'stylesheet'});
|
||||
$session->style->setLink('/extras/yui/build/datatable/assets/skins/sam/datatable.css', {type=>'text/css', rel=>'stylesheet'});
|
||||
$session->style->setLink('/extras/yui/build/button/assets/skins/sam/button.css', {type=>'text/css', rel=>'stylesheet'});
|
||||
$session->style->setScript('/extras/yui/build/yahoo-dom-event/yahoo-dom-event.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/yui/build/element/element-beta-min.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/yui/build/connection/connection-min.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/yui/build/json/json-min.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/yui/build/paginator/paginator-min.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/yui/build/datasource/datasource.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/yui/build/datatable/datatable-min.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/yui/build/button/button-min.js', {type=>'text/javascript'});
|
||||
$session->style->setScript('/extras/VendorPayout/vendorPayout.js', {type=>'text/javascript'});
|
||||
|
||||
# Add css for scheduled payout highlighting
|
||||
$session->style->setRawHeadTags(<<CSS);
|
||||
<style type="text/css">
|
||||
.yui-skin-sam .yui-dt tr.scheduled,
|
||||
.yui-skin-sam .yui-dt tr.scheduled td.yui-dt-asc,
|
||||
.yui-skin-sam .yui-dt tr.scheduled td.yui-dt-desc,
|
||||
.yui-skin-sam .yui-dt tr.scheduled td.yui-dt-asc,
|
||||
.yui-skin-sam .yui-dt tr.scheduled td.yui-dt-desc {
|
||||
background-color : #080;
|
||||
color : #fff;
|
||||
}
|
||||
</style>
|
||||
CSS
|
||||
|
||||
my $output = q{<div id="vendorPayoutContainer" class="yui-skin-sam"></div>}
|
||||
.q{<script type="text/javascript">var vp = new WebGUI.VendorPayout( 'vendorPayoutContainer' );</script>};
|
||||
|
||||
my $console = WebGUI::Shop::Admin->new($session)->getAdminConsole;
|
||||
return $console->render($output, 'Vendor payout'); #$i18n->get("vendors"));
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
|
|
|||
|
|
@ -678,6 +678,32 @@ sub generateThumbnail {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getSize ( filename )
|
||||
|
||||
Returns width and height of image.
|
||||
|
||||
=head3 filename
|
||||
|
||||
The file to generate a thumbnail for.
|
||||
|
||||
=cut
|
||||
|
||||
sub getSize {
|
||||
my $self = shift;
|
||||
my $filename = shift;
|
||||
my $image = Image::Magick->new;
|
||||
my $error = $image->Read($self->getPath($filename));
|
||||
if ($error) {
|
||||
$self->session->errorHandler->error("Couldn't read image for size reading: ".$error);
|
||||
return 0;
|
||||
}
|
||||
my ($x, $y) = $image->Get('width','height');
|
||||
|
||||
return($x, $y);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getErrorCount ( )
|
||||
|
||||
Returns the number of errors that have been generated on this object instance.
|
||||
|
|
@ -1054,6 +1080,203 @@ sub renameFile {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 crop ( filename [, width, height ] )
|
||||
|
||||
Resizes the specified image by the specified height and width. If either is omitted the iamge will be scaleed proportionately to the non-omitted one.
|
||||
|
||||
=head3 filename
|
||||
|
||||
The name of the file to resize.
|
||||
|
||||
=head3 width
|
||||
|
||||
The new width of the image in pixels.
|
||||
|
||||
=head3 height
|
||||
|
||||
The new height of the image in pixels.
|
||||
|
||||
=head3 x
|
||||
|
||||
The top of the image in pixels.
|
||||
|
||||
=head3 y
|
||||
|
||||
The top of the image in pixels.
|
||||
|
||||
=cut
|
||||
|
||||
# TODO: Make this take a hash reference with width, height, and density keys.
|
||||
|
||||
sub crop {
|
||||
my $self = shift;
|
||||
my $filename = shift;
|
||||
my $width = shift;
|
||||
my $height = shift;
|
||||
my $x = shift;
|
||||
my $y = shift;
|
||||
unless (defined $filename) {
|
||||
$self->session->errorHandler->error("Can't resize when you haven't specified a file.");
|
||||
return 0;
|
||||
}
|
||||
unless ($self->isImage($filename)) {
|
||||
$self->session->errorHandler->error("Can't resize something that's not an image.");
|
||||
return 0;
|
||||
}
|
||||
unless ($width || $height || $x || $y) {
|
||||
$self->session->errorHandler->error("Can't resize with no resizing parameters.");
|
||||
return 0;
|
||||
}
|
||||
my $image = Image::Magick->new;
|
||||
my $error = $image->Read($self->getPath($filename));
|
||||
if ($error) {
|
||||
$self->session->errorHandler->error("Couldn't read image for resizing: ".$error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Next, resize dimensions
|
||||
if ( $width || $height || $x || $y ) {
|
||||
$self->session->errorHandler->info( "Resizing $filename to w:$width h:$height x:$x y:$y" );
|
||||
$image->Crop( height => $height, width => $width, x => $x, y => $y );
|
||||
}
|
||||
|
||||
# Write our changes to disk
|
||||
$error = $image->Write($self->getPath($filename));
|
||||
if ($error) {
|
||||
$self->session->errorHandler->error("Couldn't resize image: ".$error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 annotate ( filename [ text ] )
|
||||
|
||||
Adds annotation text to the image.
|
||||
|
||||
=head3 filename
|
||||
|
||||
The name of the file to annotate.
|
||||
|
||||
=head3 text
|
||||
|
||||
Text to add.
|
||||
|
||||
=cut
|
||||
|
||||
sub annotate {
|
||||
my $self = shift;
|
||||
my $filename = shift;
|
||||
my $asset = shift;
|
||||
my $form = shift;
|
||||
unless (defined $filename) {
|
||||
$self->session->errorHandler->error("Can't rotate when you haven't specified a file.");
|
||||
return 0;
|
||||
}
|
||||
unless ($self->isImage($filename)) {
|
||||
$self->session->errorHandler->error("Can't rotate something that's not an image.");
|
||||
return 0;
|
||||
}
|
||||
# unless ($annotate_text) {
|
||||
# $self->session->errorHandler->error("Can't annotate with no text.");
|
||||
# return 0;
|
||||
# }
|
||||
# unless ($annotate_top && $annotate_left && $annotate_width && $annotate_height) {
|
||||
# $self->session->errorHandler->error("Can't annotate with no dimensions.");
|
||||
# return 0;
|
||||
# }
|
||||
|
||||
my $annotate = $asset->get('annotations');
|
||||
my $save_annotate = "";
|
||||
my @pieces = split(/\n/, $annotate);
|
||||
for (my $i = 0; $i < $#pieces; $i += 3) {
|
||||
my $top_left = $pieces[$i];
|
||||
my $width_height = $pieces[$i + 1];
|
||||
my $note = $pieces[$i + 2];
|
||||
|
||||
# warn("i: $i: ", $form->process("delAnnotate$i"));
|
||||
next if $form->process("delAnnotate$i");
|
||||
|
||||
if ($save_annotate) {
|
||||
$save_annotate .= "\n";
|
||||
}
|
||||
$save_annotate .= "$top_left\n$width_height\n$note";
|
||||
}
|
||||
|
||||
my $annotate_text = $form->process("annotate_text");
|
||||
my $annotate_top = $form->process("annotate_top");
|
||||
my $annotate_left = $form->process("annotate_left");
|
||||
my $annotate_width = $form->process("annotate_width");
|
||||
my $annotate_height = $form->process("annotate_height");
|
||||
# warn(qq(unless ($annotate_top && $annotate_left && $annotate_width && $annotate_height && $annotate_text !~ /^\s*$/)));
|
||||
if (defined $annotate_top && defined $annotate_left && defined $annotate_width && defined $annotate_height && $annotate_text !~ /^\s*$/) {
|
||||
if ($save_annotate) {
|
||||
$save_annotate .= "\n";
|
||||
}
|
||||
# warn(qq($save_annotate .= "top: ${annotate_top}px; left: ${annotate_left}px;\nwidth: ${annotate_width}px; height: ${annotate_height}px;\n'$annotate_text'"));
|
||||
$save_annotate .= "top: ${annotate_top}px; left: ${annotate_left}px;\nwidth: ${annotate_width}px; height: ${annotate_height}px;\n$annotate_text";
|
||||
}
|
||||
# warn($save_annotate);
|
||||
|
||||
$asset->update({ annotations => $save_annotate });
|
||||
$save_annotate = $asset->get('annotations');
|
||||
# warn($save_annotate);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 rotate ( filename [ degrees ] )
|
||||
|
||||
Rotates the image by the specified degrees.
|
||||
|
||||
=head3 filename
|
||||
|
||||
The name of the file to resize.
|
||||
|
||||
=head3 width
|
||||
|
||||
Number of degrees to rotate.
|
||||
|
||||
=cut
|
||||
|
||||
sub rotate {
|
||||
my $self = shift;
|
||||
my $filename = shift;
|
||||
my $degree = shift || 0;
|
||||
unless (defined $filename) {
|
||||
$self->session->errorHandler->error("Can't rotate when you haven't specified a file.");
|
||||
return 0;
|
||||
}
|
||||
unless ($self->isImage($filename)) {
|
||||
$self->session->errorHandler->error("Can't rotate something that's not an image.");
|
||||
return 0;
|
||||
}
|
||||
my $image = Image::Magick->new;
|
||||
my $error = $image->Read($self->getPath($filename));
|
||||
if ($error) {
|
||||
$self->session->errorHandler->error("Couldn't read image for resizing: ".$error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
$self->session->errorHandler->info( "Rotating $filename by $degree degrees" );
|
||||
$image->Rotate( $degree );
|
||||
|
||||
# Write our changes to disk
|
||||
$error = $image->Write($self->getPath($filename));
|
||||
if ($error) {
|
||||
$self->session->errorHandler->error("Couldn't rotate image: ".$error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 resize ( filename [, width, height ] )
|
||||
|
||||
Resizes the specified image by the specified height and width. If either is omitted the iamge will be scaleed proportionately to the non-omitted one.
|
||||
|
|
|
|||
|
|
@ -161,9 +161,9 @@ sub acceptsFriendsRequests {
|
|||
return 0 if($self->userId eq $user->userId); #Can't be your own friend (why would you want to be?)
|
||||
|
||||
my $me = WebGUI::Friends->new($session,$self);
|
||||
my $friend = WebGUI::Friends->new($session,$user);
|
||||
|
||||
return 0 if ($me->isFriend($user->userId)); #Already a friend
|
||||
|
||||
my $friend = WebGUI::Friends->new($session,$user);
|
||||
return 0 if ($me->isInvited($user->userId) || $friend->isInvited($self->userId)); #Invitation sent by one or the other
|
||||
|
||||
return $self->profileField('ableToBeFriend'); #Return profile setting
|
||||
|
|
@ -594,7 +594,13 @@ sub hasFriends {
|
|||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
# This method is depricated and is provided only for reverse compatibility. See WebGUI::Auth instead.
|
||||
|
||||
=head2 identifier
|
||||
|
||||
This method is depricated and is provided only for reverse compatibility. See WebGUI::Auth instead.
|
||||
|
||||
=cut
|
||||
|
||||
sub identifier {
|
||||
my ($self, $value);
|
||||
$self = shift;
|
||||
|
|
@ -635,8 +641,7 @@ The group that you wish to verify against the user. Defaults to group with Id 3
|
|||
=cut
|
||||
|
||||
sub isInGroup {
|
||||
my (@data, $groupId);
|
||||
my ($self, $gid, $secondRun) = @_;
|
||||
my ($self, $gid) = @_;
|
||||
$gid = 3 unless $gid;
|
||||
my $uid = $self->userId;
|
||||
### The following several checks are to increase performance. If this section were removed, everything would continue to work as normal.
|
||||
|
|
@ -997,11 +1002,12 @@ sub session {
|
|||
|
||||
=head2 setProfileFieldPrivacySetting ( settings )
|
||||
|
||||
Sets the profile field privacy settings
|
||||
Sets the profile field privacy settings. This updates the the db and
|
||||
the internally cached settings. Valid settings are "all", "none" or "friends".
|
||||
|
||||
=head3 settings
|
||||
|
||||
hash ref containing the field and it's corresponding privacy setting
|
||||
Hash ref containing fields and their corresponding privacy settings
|
||||
|
||||
=cut
|
||||
|
||||
|
|
|
|||
|
|
@ -385,7 +385,7 @@ sub sortHash {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 sortHashDecending ( hash )
|
||||
=head2 sortHashDescending ( hash )
|
||||
|
||||
Sorts a hash in decending order by its values. Returns a Tie::IxHash.
|
||||
You must assign this to a similarly tied hash to preserve the order.
|
||||
|
|
@ -396,7 +396,6 @@ A hash to be sorted.
|
|||
|
||||
=cut
|
||||
|
||||
|
||||
sub sortHashDescending {
|
||||
my %hash = @_;
|
||||
tie my %newHash, 'Tie::IxHash';
|
||||
|
|
@ -408,5 +407,3 @@ sub sortHashDescending {
|
|||
|
||||
|
||||
1;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -23,12 +23,12 @@ use WebGUI::Inbox;
|
|||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Workflow::Activity::NotifyAboutUser
|
||||
Package WebGUI::Workflow::Activity::NotifyAboutLowStock
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Takes a user object and sends out a message. Can use macros in message, to and subject
|
||||
fields.
|
||||
Notify group about users when Products fall below a configurable amount of stock
|
||||
in inventory.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
|
|
|
|||
110
lib/WebGUI/Workflow/Activity/RemoveOldCarts.pm
Normal file
110
lib/WebGUI/Workflow/Activity/RemoveOldCarts.pm
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
package WebGUI::Workflow::Activity::RemoveOldCarts;
|
||||
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2009 Plain Black Corporation.
|
||||
-------------------------------------------------------------------
|
||||
Please read the legal notices (docs/legal.txt) and the license
|
||||
(docs/license.txt) that came with this distribution before using
|
||||
this software.
|
||||
-------------------------------------------------------------------
|
||||
http://www.plainblack.com info@plainblack.com
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use base 'WebGUI::Workflow::Activity';
|
||||
use WebGUI::International;
|
||||
use WebGUI::Asset::Sku::Product;
|
||||
use WebGUI::Inbox;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Workflow::Activity::RemoveOldCarts
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Remove carts that are older than a configurable threshold.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
See WebGUI::Workflow::Activity for details on how to use any activity.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
These methods are available from this class:
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( session, definition )
|
||||
|
||||
See WebGUI::Workflow::Activity::defintion() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, 'Workflow_Activity_RemoveOldCarts');
|
||||
push(@{$definition}, {
|
||||
name=>$i18n->get('activityName'),
|
||||
properties=> {
|
||||
cartTimeout => {
|
||||
fieldType=>'interval',
|
||||
label=>$i18n->get('cart timeout'),
|
||||
defaultValue=>48*3600,
|
||||
hoverHelp=>$i18n->get('cart timeout help'),
|
||||
},
|
||||
}
|
||||
});
|
||||
return $class->SUPER::definition($session,$definition);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 execute ( [ object ] )
|
||||
|
||||
See WebGUI::Workflow::Activity::execute() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub execute {
|
||||
my ($self) = @_;
|
||||
my $session = $self->session;
|
||||
my $now = time();
|
||||
my $finishTime = $now + $self->getTTL;
|
||||
my $expired = 0;
|
||||
my $cartIds = [];
|
||||
my $limit = $now - $self->get('cartTimeout');
|
||||
$session->log->warn("limit: $limit");
|
||||
my $expiredCarts = $session->db->read('select cartId from cart where creationDate < '.$limit);
|
||||
$expiredCarts->execute();
|
||||
CART: while( my ($cartId) = $expiredCarts->array() ) {
|
||||
my $cart = eval {
|
||||
WebGUI::Shop::Cart->new($session, $cartId);
|
||||
};
|
||||
next CART if WebGUI::Error->caught;
|
||||
$session->log->warn("cartId: $cartId");
|
||||
$cart->delete; ##Delete will empty, then delete.
|
||||
##Time check and set flag
|
||||
if (time() > $finishTime) {
|
||||
$expired = 1;
|
||||
last CART;
|
||||
}
|
||||
}
|
||||
##If timer expired, then store message and limit and release
|
||||
if ($expired) {
|
||||
return $self->WAITING(1);
|
||||
}
|
||||
|
||||
return $self->COMPLETE;
|
||||
}
|
||||
|
||||
1;
|
||||
114
lib/WebGUI/i18n/English/AssetAspect_RssFeed.pm
Normal file
114
lib/WebGUI/i18n/English/AssetAspect_RssFeed.pm
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
package WebGUI::i18n::English::AssetAspect_RssFeed;
|
||||
use strict;
|
||||
|
||||
our $I18N = {
|
||||
|
||||
'itemsPerFeed' => {
|
||||
message => q|Items Per Feed|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The name of the itemsPerFeed field.|
|
||||
},
|
||||
|
||||
'itemsPerFeed hoverHelp' => {
|
||||
message => q|The number of items to include in the feed.|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The hoverhelp of the itemsPerFeed field.|
|
||||
},
|
||||
|
||||
'feedCopyright' => {
|
||||
message => q|Feed Copyright|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The name of the feedCopyright field.|
|
||||
},
|
||||
|
||||
'feedCopyright hoverHelp' => {
|
||||
message => q|An optional copyright notice for the feed.|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The hoverhelp of the feedCopyright field.|
|
||||
},
|
||||
|
||||
'feedTitle' => {
|
||||
message => q|Feed Title|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The name of the feedTitle field.|
|
||||
},
|
||||
|
||||
'feedTitle hoverHelp' => {
|
||||
message => q|An optional title for the feed. If not specified the asset's title will be used instead.|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The hoverhelp of the feedTitle field.|
|
||||
},
|
||||
|
||||
'feedDescription' => {
|
||||
message => q|Feed Description|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The name of the feedDescription field.|
|
||||
},
|
||||
|
||||
'feedDescription hoverHelp' => {
|
||||
message => q|An optional description for the feed. If not specified the asset's synopsis will be used instead.|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The hoverhelp of the feedDescription field.|
|
||||
},
|
||||
|
||||
'feedImage' => {
|
||||
message => q|Feed Image|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The name of the feedImage field.|
|
||||
},
|
||||
|
||||
'feedImage hoverHelp' => {
|
||||
message => q|An optional image that can be uploaded for the feed.|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The hoverhelp of the feedImage field.|
|
||||
},
|
||||
|
||||
'feedImageLink' => {
|
||||
message => q|Feed Image Link|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The name of the feedImageLink field.|
|
||||
},
|
||||
|
||||
'feedImageLink hoverHelp' => {
|
||||
message => q|An optional URL that will link the image to a specific location. If not specified the asset's URL will be used instead.|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The hoverhelp of the feedImageLink field.|
|
||||
},
|
||||
|
||||
'feedImageDescription' => {
|
||||
message => q|Feed Image Description|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The name of the feedImageDescription field.|
|
||||
},
|
||||
|
||||
'feedImageDescription hoverHelp' => {
|
||||
message => q|An optional description for the image. If not specified the asset's title will be used instead.|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The hoverhelp of the feedImageDescription field.|
|
||||
},
|
||||
|
||||
'RSS tab' => {
|
||||
message => q|RSS|,
|
||||
lastUpdated => 1236820473,
|
||||
context => q|The title of the RSS tab on the asset's edit form.|
|
||||
},
|
||||
|
||||
'feedHeaderLinks' => {
|
||||
message => q|HTML Header Feed Links|,
|
||||
},
|
||||
'feedHeaderLinks hoverHelp' => {
|
||||
message => q|Select which feed types to include in the HTML headers, which many browsers will offer as options to users.|,
|
||||
},
|
||||
'rssLinkOption' => {
|
||||
message => q|RSS 2.0|,
|
||||
},
|
||||
'atomLinkOption' => {
|
||||
message => 'Atom',
|
||||
},
|
||||
'rdfLinkOption' => {
|
||||
message => 'RDF/RSS 1.0',
|
||||
},
|
||||
};
|
||||
|
||||
1;
|
||||
#vim:ft=perl
|
||||
266
lib/WebGUI/i18n/English/Asset_AdSku.pm
Normal file
266
lib/WebGUI/i18n/English/Asset_AdSku.pm
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
package WebGUI::i18n::English::Asset_AdSku;
|
||||
use strict;
|
||||
|
||||
our $I18N = {
|
||||
'assetName' => {
|
||||
message => q|Ad Sales|,
|
||||
lastUpdated => 0,
|
||||
context => q|The name of the Ad Sales asset|,
|
||||
},
|
||||
|
||||
|
||||
'property purchase template' => {
|
||||
message => q|Purchase Template|,
|
||||
lastUpdated => 0,
|
||||
context => q|The name of the template to use for purchasing ad space.|
|
||||
},
|
||||
|
||||
'property purchase template help' => {
|
||||
message => q|Select a template to use for purchasing ad space.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Select a template to use for purchasing ad space.|
|
||||
},
|
||||
|
||||
'property manage template' => {
|
||||
message => q|Manage Template|,
|
||||
lastUpdated => 0,
|
||||
context => q|The name of the template to use for managing ad space.|
|
||||
},
|
||||
|
||||
'property manage template help' => {
|
||||
message => q|Select a template to use for managing ad space.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Select a template to use for managing ad space.|
|
||||
},
|
||||
|
||||
'property ad space' => {
|
||||
message => q|Ad Space|,
|
||||
lastUpdated => 0,
|
||||
context => q|The ad space being sold here.|
|
||||
},
|
||||
|
||||
'property ad Space help' => {
|
||||
message => q|Select the ad space being sold by this SKU.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Select the ad space being sold by this SKU.|
|
||||
},
|
||||
|
||||
'property priority' => {
|
||||
message => q|Priority|,
|
||||
lastUpdated => 0,
|
||||
context => q|The priority of the ads sold by this SKU.|
|
||||
},
|
||||
|
||||
'property priority help' => {
|
||||
message => q|Indicate the priority of ads sold by this SKU. You can use multiple SKU's to sell the same ad space at different rates by setting different priorities for each SKU.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Help text for the priority field on the AdSku Edit page.|
|
||||
},
|
||||
|
||||
'property price per click' => {
|
||||
message => q|Price Per Click|,
|
||||
lastUpdated => 0,
|
||||
context => q|The price charged per click.|
|
||||
},
|
||||
|
||||
'property price per click help' => {
|
||||
message => q|Indicate how much to charge for each click purchased.|,
|
||||
lastUpdated => 1165511641,
|
||||
context => q|Help for the price per click field.|
|
||||
},
|
||||
|
||||
'property price per impression' => {
|
||||
message => q|Price Per Impression|,
|
||||
lastUpdated => 0,
|
||||
context => q|The price charged for each impression of this ad.|
|
||||
},
|
||||
|
||||
'property price per impression help' => {
|
||||
message => q|Indicate how much to charge for each impression purchased.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Help text for the price per impression field.|
|
||||
},
|
||||
|
||||
'property click discounts' => {
|
||||
message => q|Click Discounts|,
|
||||
lastUpdated => 0,
|
||||
context => q|The discounts offered based on number of clicks.|
|
||||
},
|
||||
|
||||
'property click discounts help' => {
|
||||
message => q|Enter discounts one per line at the start of the line. Extra text is ignored so you can add comments to the discounts. Each discount consists of two numbers seperated by '@' with no spaces. The first number is the percent discount(no decimal point) the second number is the number of items purchased. So 5@1000 indicates a 5% discount for 1000 or more clicks purchased.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Help text for the click discounts field.|
|
||||
},
|
||||
|
||||
'property impression discounts' => {
|
||||
message => q|Impression Discounts|,
|
||||
lastUpdated => 0,
|
||||
context => q|The discounts offered based on number of impressions purchased.|
|
||||
},
|
||||
|
||||
'property impression discounts help' => {
|
||||
message => q|Enter discounts one per line at the start of the line. Extra text is ignored so you can add comments to the discounts. Each discount consists of two numbers seperated by '@' with no spaces. The first number is the percent discount(no decimal point) the second number is the number of items purchased. So 5@1000 indicates a 5% discount for 1000 or more impressions purchased.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Help text for the impresison discounts field.|
|
||||
},
|
||||
|
||||
'property adsku karma' => {
|
||||
message => q|karma|,
|
||||
lastUpdated => 0,
|
||||
context => q|The karm field name.|
|
||||
},
|
||||
|
||||
'property adsku karma description' => {
|
||||
message => q|how much karma does this offer|,
|
||||
lastUpdated => 0,
|
||||
context => q|Description for the karma field.|
|
||||
},
|
||||
|
||||
'form purchase per click' => {
|
||||
message => q|@ %f per click|,
|
||||
lastUpdated => 0,
|
||||
context => q|%f is the price charged for each click on the ad.|
|
||||
},
|
||||
|
||||
'form purchase per impression' => {
|
||||
message => q|@ %f per impression|,
|
||||
lastUpdated => 0,
|
||||
context => q|%f is the price charged for each impression of the ad.|
|
||||
},
|
||||
|
||||
'form manage title' => {
|
||||
message => q|Manage My Ads|,
|
||||
lastUpdated => 0,
|
||||
context => q|Text for the title of the form where the user can manage previously purchased advertisements.|
|
||||
},
|
||||
|
||||
'form manage link' => {
|
||||
message => q|Manage My Ads|,
|
||||
lastUpdated => 0,
|
||||
context => q|Text for a link to the form where the user can manage previously purchased advertisements.|
|
||||
},
|
||||
|
||||
'form purchase link' => {
|
||||
message => q|Purchase Ads|,
|
||||
lastUpdated => 0,
|
||||
context => q|Text for a link to the form where the user can purchase advertisements,|
|
||||
},
|
||||
|
||||
'form manage table header title' => {
|
||||
message => q|Title|,
|
||||
lastUpdated => 0,
|
||||
context => q|Header for the adspace manage form: the title field.|
|
||||
},
|
||||
|
||||
'form manage table header clicks' => {
|
||||
message => q|Clicks|,
|
||||
lastUpdated => 0,
|
||||
context => q|Header for the adspace manage form: the clicks field.|
|
||||
},
|
||||
|
||||
'form manage table header impressions' => {
|
||||
message => q|Impressions|,
|
||||
lastUpdated => 0,
|
||||
context => q|Header for the adspace manage form: the impressions field.|
|
||||
},
|
||||
|
||||
'form manage table header renew' => {
|
||||
message => q|Renew|,
|
||||
lastUpdated => 0,
|
||||
context => q|Header for the adspace manage form: the renew field.|
|
||||
},
|
||||
|
||||
'form manage table value deleted' => {
|
||||
message => q|Deleted|,
|
||||
lastUpdated => 0,
|
||||
context => q|Contents for the renew field on the manage ads table: indicates a deleted item.|
|
||||
},
|
||||
|
||||
'form manage table value renew' => {
|
||||
message => q|Renew|,
|
||||
lastUpdated => 0,
|
||||
context => q|Contents for the renew field on the manage ads table: indicates a renewable item.|
|
||||
},
|
||||
|
||||
'form purchase button' => {
|
||||
message => q|Add To Cart|,
|
||||
lastUpdated => 0,
|
||||
context => q|Add the described item to the shopping cart.|
|
||||
},
|
||||
|
||||
'form purchase ad title' => {
|
||||
message => q|Ad Title|,
|
||||
lastUpdated => 0,
|
||||
context => q|The title chosen by the buyer for the advertisement.|
|
||||
},
|
||||
|
||||
'form purchase ad link' => {
|
||||
message => q|Ad Link|,
|
||||
lastUpdated => 0,
|
||||
context => q|The link the advertisement leads to.|
|
||||
},
|
||||
|
||||
'form purchase ad image' => {
|
||||
message => q|Image|,
|
||||
lastUpdated => 0,
|
||||
context => q|The image to be displayed in the ad.|
|
||||
},
|
||||
|
||||
'form purchase number of clicks' => {
|
||||
message => q|Number of Clicks|,
|
||||
lastUpdated => 0,
|
||||
context => q|The number of clicks the buyer wishes to purchase.|
|
||||
},
|
||||
|
||||
'form purchase number of impressions' => {
|
||||
message => q|Number of Impressions|,
|
||||
lastUpdated => 0,
|
||||
context => q|The number of impressions the user wishes to purchase.|
|
||||
},
|
||||
|
||||
'form added to cart thanks' => {
|
||||
message => q|Thank you very much for your purchase.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Thank the customer after adding the item to the cart.|
|
||||
},
|
||||
|
||||
'form error no image' => {
|
||||
message => q|Please assign an image for this ad.|,
|
||||
lastUpdated => 0,
|
||||
context => q|remind the user to upload an image for the ad.|
|
||||
},
|
||||
|
||||
'form error no title' => {
|
||||
message => q|Please enter the title for this ad.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Remind the user to enter a title for the ad.|
|
||||
},
|
||||
|
||||
'form error no link' => {
|
||||
message => q|Please enter a valid URL for this ad.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Remind the user to enter a valid URL for the ad.|
|
||||
},
|
||||
|
||||
'form error min clicks' => {
|
||||
message => q|You must purchase at least %d clicks for this adSpace.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Remind the user to that they must purchase a minimum number of clicks, use '%d' to indicate the minimum number of clicks.|
|
||||
},
|
||||
|
||||
'form error min impressions' => {
|
||||
message => q|You must purchase at least %d impressions for this adSpace.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Remind the user to that they must purchase a minimum number of impressions, use '%d' to indicate the minimum number of impressions.|
|
||||
},
|
||||
|
||||
# 'TODO' => {
|
||||
# message => q|TODO|,
|
||||
# lastUpdated => 0,
|
||||
# context => q|TODO|
|
||||
# },
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
80
lib/WebGUI/i18n/English/Asset_Carousel.pm
Normal file
80
lib/WebGUI/i18n/English/Asset_Carousel.pm
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
package WebGUI::i18n::English::Asset_Carousel;
|
||||
|
||||
use strict;
|
||||
|
||||
our $I18N = {
|
||||
'assetName' => {
|
||||
message => q|Carousel|,
|
||||
lastUpdated => 0,
|
||||
context => q|The name of this asset, used in the admin bar.|
|
||||
},
|
||||
|
||||
'carousel template label' => {
|
||||
message => q|Carousel template|,
|
||||
lastUpdated => 0,
|
||||
context => q|Label of the carousel template field on the edit screen.|
|
||||
},
|
||||
|
||||
'carousel template description' => {
|
||||
message => q|Select a template for this carousel.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Description of the carousel template field, used as hover help.|
|
||||
},
|
||||
|
||||
'items label' => {
|
||||
message => q|Items|,
|
||||
lastUpdated => 0,
|
||||
context => q|Label of the items field on the edit screen.|
|
||||
},
|
||||
|
||||
'items description' => {
|
||||
message => q|Enter this carousel's items.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Description of the items field, used as hover help.|
|
||||
},
|
||||
|
||||
'id label' => {
|
||||
message => q|ID|,
|
||||
lastUpdated => 0,
|
||||
context => q|Label of the item ID field on the edit screen.|
|
||||
},
|
||||
|
||||
'id description' => {
|
||||
message => q|Enter a unique ID for this carousel item.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Description of the item ID field, used as hover help.|
|
||||
},
|
||||
|
||||
'carousel template help title' => {
|
||||
message => q|Carousel Template Variables|,
|
||||
lastUpdated => 0,
|
||||
context => q|Title of a template help page.|
|
||||
},
|
||||
|
||||
'item_loop' => {
|
||||
message => q|A loop containing this carousel's items.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Description of the item_loop tmpl_loop for the template help.|
|
||||
},
|
||||
|
||||
'itemId' => {
|
||||
message => q|This carousel item's id.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Description of the itemId tmpl_var for the template help.|
|
||||
},
|
||||
|
||||
'text' => {
|
||||
message => q|This carousel item's text.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Description of the text tmpl_var for the template help.|
|
||||
},
|
||||
|
||||
'sequenceNumber' => {
|
||||
message => q|This carousel item's sequenceNumber.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Description of the sequenceNumber tmpl_var for the template help.|
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
#vim:ft=perl
|
||||
|
|
@ -127,6 +127,7 @@ our $I18N = {
|
|||
lastUpdated => 0,
|
||||
context => 'Label for button to submit search form',
|
||||
},
|
||||
|
||||
"templateIdAddArchive label" => {
|
||||
message => "Template to Add Multiple",
|
||||
lastUpdated => 0,
|
||||
|
|
@ -741,6 +742,25 @@ our $I18N = {
|
|||
lastUpdated => 0,
|
||||
context => q{Option label for 300 pixels-per-inch images, good for printing images},
|
||||
},
|
||||
|
||||
'template listAlbumsRss' => {
|
||||
message => 'Subscribe',
|
||||
lastUpdated => 1237403207,
|
||||
context => 'Label for link to RSS feed.',
|
||||
},
|
||||
|
||||
'template search basic title' => {
|
||||
message => 'Search Gallery',
|
||||
lastUpdated => 1237403442,
|
||||
context => 'Title for basic search form in page.',
|
||||
},
|
||||
|
||||
'template search basic term' => {
|
||||
message => 'Search Term',
|
||||
lastUpdated => 1237403498,
|
||||
context => 'Title for basic search term field in page.',
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -574,6 +574,18 @@ our $I18N = {
|
|||
context => q{template label in the Edit Album template. To pick a thumbnail to use to represent the Album.},
|
||||
},
|
||||
|
||||
'template album thumbnail alt' => {
|
||||
message => 'Preview thumbnail for',
|
||||
lastUpdated => 1237404629,
|
||||
context => 'Alt text for album thumbnail.',
|
||||
},
|
||||
|
||||
'template url_addDescription' => {
|
||||
message => 'Add a Description',
|
||||
lastUpdated => 1237405184,
|
||||
context => 'Label for URL to add an album Description.',
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -77,6 +77,54 @@ shown here.|,
|
|||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'annotate' => {
|
||||
message => q|Annotate|,
|
||||
context => q|label to annotate the image|,
|
||||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'annotate image' => {
|
||||
message => q|Annotate Image|,
|
||||
context => q|label to annotate the image|,
|
||||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'annotate image description' => {
|
||||
message => q|Text Around the Image|,
|
||||
context => q|label to annotate the image|,
|
||||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'degree' => {
|
||||
message => q|Degrees to Rotate|,
|
||||
context => q|label to rotate the image|,
|
||||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'rotate image label' => {
|
||||
message => q|Please click to rotate image|,
|
||||
context => q|label to rotate the image|,
|
||||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'rotate image' => {
|
||||
message => q|Rotate Image|,
|
||||
context => q|label to rotate the image|,
|
||||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'rotate image label' => {
|
||||
message => q|Please click to rotate image|,
|
||||
context => q|label to rotate the image|,
|
||||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'crop image' => {
|
||||
message => q|Crop Image|,
|
||||
context => q|label to crop the image|,
|
||||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'new width' => {
|
||||
message => q|New Width|,
|
||||
context => q|label to resize the image|,
|
||||
|
|
@ -101,6 +149,42 @@ shown here.|,
|
|||
lastUpdated => 1130538987
|
||||
},
|
||||
|
||||
'undo image' => {
|
||||
message => q|Undo Image|,
|
||||
context => q|undo editing operations|,
|
||||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'delete' => {
|
||||
message => q|Delete|,
|
||||
context => q|label to delete annotation|,
|
||||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'height' => {
|
||||
message => q|Height|,
|
||||
context => q|label to resize the image|,
|
||||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'width' => {
|
||||
message => q|Width|,
|
||||
context => q|label to resize the image|,
|
||||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'top' => {
|
||||
message => q|Top|,
|
||||
context => q|label to resize the image|,
|
||||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'left' => {
|
||||
message => q|Left|,
|
||||
context => q|label to resize the image|,
|
||||
lastUpdated => 1106765841
|
||||
},
|
||||
|
||||
'image template title' => {
|
||||
message => q|Image Template Variables|,
|
||||
lastUpdated => 1184820779,
|
||||
|
|
|
|||
|
|
@ -427,6 +427,17 @@ listing,|,
|
|||
lastUpdated => 1235681965,
|
||||
},
|
||||
|
||||
'statistics cache timeout label' => {
|
||||
message => q|Statistics Cache Timeout|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'statistics cache timeout description' => {
|
||||
message => q|Since all users will see the matrix statistics the same way, we can cache them for some time
|
||||
to increase performance. How long should we cache them?|,
|
||||
lastUpdated => 0,
|
||||
},
|
||||
|
||||
'rating timeout description' => {
|
||||
message => q|Set a timeout so that users are prevented from rating a given listing too often.|,
|
||||
lastUpdated => 1135271460,
|
||||
|
|
|
|||
|
|
@ -136,10 +136,10 @@ all of the classes of pages that should be included:<br />
|
|||
<dd>The current page.</dd>
|
||||
<dt>Siblings</dt>
|
||||
<dd>Pages at the same level as the current URL.</dd>
|
||||
<dt>Descendents</dt>
|
||||
<dt>Descendants</dt>
|
||||
<dd>Pages lower than the current page in the tree.</dd>
|
||||
<dt>Pedigree</dt>
|
||||
<dd>When using a different start page, this option selects the Ancestors, Siblings and Descendents of that page.</dd>
|
||||
<dd>When using a different start page, this option selects the Ancestors, Siblings and Descendants of that page.</dd>
|
||||
</dl>|,
|
||||
lastUpdated => 1146456217,
|
||||
},
|
||||
|
|
@ -372,7 +372,7 @@ the Navigation Template to determine who can see them in the menu.</p>
|
|||
lastUpdated => 1163720148,
|
||||
},
|
||||
|
||||
'page.isDescendent' => {
|
||||
'page.isDescendant' => {
|
||||
message => q|A conditional indicating whether this page is a descendant of the current page.|,
|
||||
lastUpdated => 1163720154,
|
||||
},
|
||||
|
|
@ -393,7 +393,7 @@ the Navigation Template to determine who can see them in the menu.</p>
|
|||
},
|
||||
|
||||
'page.inBranch' => {
|
||||
message => q|A conditional that is the logical OR of <strong>isAncestor</strong>, <strong>isSibling</strong>, <strong>isBasepage</strong> and <strong>isDescendent</strong>.|,
|
||||
message => q|A conditional that is the logical OR of <strong>isAncestor</strong>, <strong>isSibling</strong>, <strong>isBasepage</strong> and <strong>isDescendant</strong>.|,
|
||||
lastUpdated => 1157647394,
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
package WebGUI::i18n::English::Asset_RSSCapable;
|
||||
use strict;
|
||||
|
||||
our $I18N =
|
||||
{
|
||||
'rssEnabled label' => { message => 'Enable RSS', lastUpdate => 1162487361 },
|
||||
'rssEnabled hoverHelp' => { message => q|Whether or not to enable the RSS feed for this asset. If enabled, an RSS From Parent asset will be created and managed as an extra child for this purpose. If not enabled, no such child will be created and the existing one will be deleted.|, lastUpdate => 1162487361 },
|
||||
'rssTemplateId label' => { message => 'RSS Template', lastUpdate => 1162487361 },
|
||||
'rssTemplateId hoverHelp' => { message => q|The template to use for the RSS feed of this asset.|, lastUpdate => 1162487361 },
|
||||
|
||||
'assetName' => { message => 'RSS Capable', lastUpdate => 1162487361 },
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
package WebGUI::i18n::English::Asset_RSSFromParent;
|
||||
use strict;
|
||||
|
||||
our $I18N =
|
||||
{
|
||||
'assetName' => { message => 'RSS From Parent', lastUpdated => 1162257377 },
|
||||
|
||||
'rss from parent title' => {
|
||||
message => 'RSS From Parent',
|
||||
lastUpdated => 1162257377
|
||||
},
|
||||
|
||||
'rss from parent body' => {
|
||||
message => q|<p>The sole purpose of this Asset is to provide a base template for generating RSS Feeds. Below are listed the basic template variables available to any valid RSS generating Asset. Assets may provide additional or different variables.</p>|,
|
||||
lastUpdated => 1162257377
|
||||
},
|
||||
|
||||
'title.parent' => {
|
||||
message => 'The title of the parent of this Asset',
|
||||
lastUpdated => 1162257377
|
||||
},
|
||||
|
||||
'title.item' => {
|
||||
message => 'The title of this Asset',
|
||||
lastUpdated => 1162257377
|
||||
},
|
||||
|
||||
'link' => {
|
||||
message => 'link',
|
||||
lastUpdated => 1162257377
|
||||
},
|
||||
|
||||
'link.parent' => {
|
||||
message => 'The url of the parent of this Asset',
|
||||
lastUpdated => 1162257377
|
||||
},
|
||||
|
||||
'link.item' => {
|
||||
message => 'The url of this Asset',
|
||||
lastUpdated => 1162257377
|
||||
},
|
||||
|
||||
'description' => {
|
||||
message => 'description',
|
||||
lastUpdated => 1162257377
|
||||
},
|
||||
|
||||
'description.parent' => {
|
||||
message => 'The description of the parent of this Asset',
|
||||
lastUpdated => 1162257377
|
||||
},
|
||||
|
||||
'description.item' => {
|
||||
message => 'The description of this Asset',
|
||||
lastUpdated => 1162257377
|
||||
},
|
||||
|
||||
'generator' => {
|
||||
message => 'A string that identifies that this RSS was generated by WebGUI and also by what version of WebGUI.',
|
||||
lastUpdated => 1162257377
|
||||
},
|
||||
|
||||
'lastBuildDate' => {
|
||||
message => q|The date the parent's content was last modified in the proper format for RSS (RFC 822).|,
|
||||
lastUpdated => 1162257377
|
||||
},
|
||||
|
||||
'webMaster' => {
|
||||
message => q|The company email address from the WebGUI Settings.|,
|
||||
lastUpdated => 1162257377
|
||||
},
|
||||
|
||||
'docs' => {
|
||||
message => q|The URL http://blogs.law.harvard.edu/tech/rss, which links to the RSS 2.0 specification.|,
|
||||
lastUpdated => 1162257377
|
||||
},
|
||||
|
||||
'item_loop' => {
|
||||
message => q|A loop containing information about all Assets below the parent.|,
|
||||
lastUpdated => 1162957711
|
||||
},
|
||||
|
||||
'guid' => {
|
||||
message => q|An alias for link. In RSS, guid is the unique identifier for this item.|,
|
||||
lastUpdated => 1162957711
|
||||
},
|
||||
|
||||
'pubDate' => {
|
||||
message => q|The date this item was last modified in the proper format for RSS (RFC 822).|,
|
||||
lastUpdated => 1162958127
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue