Added SQLReport download and Product AddToGroup handler

This commit is contained in:
Doug Bell 2006-10-10 18:14:31 +00:00
parent 03822a9488
commit 6d56df1362
13 changed files with 946 additions and 28 deletions

View file

@ -19,6 +19,7 @@ use WebGUI::SQL;
use WebGUI::Utility;
use WebGUI::Asset::Wobject;
use WebGUI::Cache;
use WebGUI::Text qw(:csv);
our @ISA = qw(WebGUI::Asset::Wobject);
@ -153,6 +154,30 @@ sub definition {
fieldType=>"yesNo",
defaultValue=>0
},
# download
downloadType=>{
fieldType=>"text",
defaultValue=>"",
},
downloadFilename=>{
fieldType=>"text",
defaultValue=>"",
},
downloadTemplateId=>{
fieldType=>"template",
defaultValue=>'SQLReportDownload0001',
},
downloadMimeType=>{
fieldType=>"text",
defaultValue=>"text/html",
},
downloadUserGroup=>{
fieldType=>"group",
defaultValue=>"text/html",
},
}
});
return $class->SUPER::definition($session, $definition);
@ -182,7 +207,79 @@ sub getEditForm {
-uiLevel => 8,
-value=>$self->getValue("cacheTimeout")
);
### Download
# Download Type
my %downloadTypes;
tie %downloadTypes, 'Tie::IxHash',
"none" => "No Download",
"csv" => "CSV",
"template" => "Template",
;
$tabform->getTab("properties")->radioList(
-name=>"downloadType", # ID is downloadType_formId
-label=>$i18n->get("download type"),
-hoverHelp=>$i18n->get("download type description"),
-vertical=>1,
-options=> \%downloadTypes,
-defaultValue=>"none",
-value=>$self->getValue("downloadType"),
-extras=> "onclick='changeDownloadType(this)'"
);
# Download Filename
$tabform->getTab("properties")->text(
-name=>"downloadFilename", # ID is downloadFilename_formId
-label=>$i18n->get("download filename"),
-hoverHelp=>$i18n->get("download filename description"),
-value=>$self->getValue("downloadFilename"),
);
# Download template (if necessary)
$tabform->getTab("properties")->template(
-name=>"downloadTemplateId", # ID is downloadTemplateId_formId
-label=>$i18n->get("download template"),
-hoverHelp=>$i18n->get("download template description"),
-value=>$self->getValue("downloadTemplateId"),
-namespace=>"SQLReport/Download",
);
# Download mimeType (if necessary)
my %downloadMimeType;
tie %downloadMimeType, 'Tie::IxHash',
"application/octet-stream" => "application/octet-stream",
"application/xml" => "application/xml",
"application/csv" => "application/csv",
"text/html" => "text/html",
"text/plain" => "text/plain",
;
$tabform->getTab("properties")->selectBox(
-name=>"downloadMimeType",
-label=>$i18n->get("download mimetype"),
-hoverHelp=>$i18n->get("download mimetype description"),
-options=> \%downloadMimeType,
-value=>$self->getValue("downloadMimeType"),
-defaultValue=>"application/octet-stream",
);
# Download UserGroup
$tabform->getTab("security")->group(
-name=>"downloadUserGroup",
-label=>$i18n->get("download usergroup"),
-hoverHelp=>$i18n->get("download usergroup description"),
-value=>$self->getValue("downloadUserGroup"),
-defaultValue=>$self->getValue("groupIdView"),
);
# javascript
$self->session->style->setScript("/extras/wobject/SQLReport/editFormDownload.js");
### /DOWNLOAD
# Add toggleQuery javascript
$tabform->getTab("properties")->raw(qq|
<script type="text/javascript">
@ -274,6 +371,64 @@ sub getEditForm {
}
#-------------------------------------------------------------------
=head2 download ( )
Returns the SQLReport in the configured manner. Returns nothing if download is
not enabled.
=cut
sub download {
my $self = shift;
# Instead of going through some costly exercises...
return if ($self->getValue("downloadType") eq "none");
# Initiate an empty debug loop
$self->{_debug_loop} = [] ;
# Store queries in class
$self->_storeQueries();
# Call _processQuery
my $data = $self->_processQuery(0,0);
# If we're downloading CSV
if ($self->getValue("downloadType") eq "csv") {
my $out = "";
### Loop through the returned structure and put it through Text::CSV
# Column heads
$out .= joinCSV(
map { $_->{"field.name"} }
@{$data->{rows_loop}->[0]->{"row.field_loop"}}
);
# Data lines
for my $row (@{$data->{rows_loop}}) {
$out .= "\n".joinCSV(map { $_->{"field.value"} }
@{$row->{"row.field_loop"}}
);
}
return $out;
} elsif ($self->getValue("downloadType") eq "template") {
return $self->processTemplate($data,$self->get("downloadTemplateId"));
} else {
# I don't know what to do
return;
}
}
#-------------------------------------------------------------------
=head2 prepareView ( )
@ -324,6 +479,13 @@ sub view {
# Add debug loop to template vars
$var->{'debug_loop'} = $self->{_debug_loop};
#use Data::Dumper; return '<pre>'.Dumper($var).'</pre>';
# Add the "Download data" link if the user is allowed to download
$var->{'canDownload'} = 1
if ($self->getValue("downloadType") ne "none"
&& $self->session->user->isInGroup($self->getValue("downloadUserGroup"))
);
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"));
@ -370,9 +532,20 @@ sub _parsePlaceholderParams {
#-------------------------------------------------------------------
# _processQuery($nest, $page, $nr)
# Recursive sub to process this SQLReport's queries.
# Arguments: $nest - If true, will run the nested queries. Defaults to true
# $page - If true, will paginate. Defaults to true
# $nr - This query number. Defaults to one. This is used
# internally to tell which query we're performing. You should not
# send this yourself.
# Returns: A reference to a datastructure containing template variables to
# be passed to processTemplate()
sub _processQuery {
my $self = shift;
my $nr = shift || 1;
my $self = shift;
my $nest = shift || 1;
my $page = shift || 1;
my $nr = shift || 1;
my ($query, %var, $prefix);
if($nr > 1) {
@ -427,8 +600,16 @@ sub _processQuery {
.'='.$self->session->url->escape($self->session->form->process($_)));
}
}
my $paginateAfter = $self->get("paginateAfter");
$paginateAfter = 1000 if($self->{_query}{$nr + 1}{dbQuery});
my $paginateAfter;
if ($page) # Set page length
{
$paginateAfter = $self->get("paginateAfter");
$paginateAfter = 1000 if($self->{_query}{$nr + 1}{dbQuery});
}
else
{
$paginateAfter = 1000000;
}
my $p = WebGUI::Paginator->new($self->session,$url,$paginateAfter);
my $error = $p->setDataByQuery($query,$dbh,1,$placeholderParams);
if ($error ne "") {
@ -461,8 +642,8 @@ sub _processQuery {
$row{$prefix.'row.field.'.$name.'.value'} = $data->{$name};
}
# Process nested query
if($self->{_query}{$nr + 1}{dbQuery}) {
my $nest = $self->_processQuery($nr+1);
if($nest && $self->{_query}{$nr + 1}{dbQuery}) {
my $nest = $self->_processQuery($nest,$page,$nr+1);
%row = (%row , %$nest);
$row{$prefix.'hasNest'} = $nest->{'query'.($nr+1).'.rows.count'};
}
@ -492,6 +673,42 @@ sub _processQuery {
return \%var;
}
#-------------------------------------------------------------------
=head2 www_download ( )
Calls download() to let user download the SQLReport in the configured manner.
=cut
sub www_download {
my $self = shift;
# Only allow if download type is not "none"
return if $self->getValue("downloadType") eq "none";
# Only allow users in appropriate group
return $self->session->privilege->noAccess()
unless $self->session->user->isInGroup($self->getValue("downloadUserGroup"));
# Set filename and mimetype
if ($self->getValue("downloadType") eq "csv")
{
$self->session->http->setFilename($self->getValue("downloadFilename"),"application/octet-stream");
}
else
{
$self->session->http->setFilename($self->getValue("downloadFilename"),$self->getValue("downloadMimeType"));
}
$self->session->http->sendHeader;
return $self->download;
}
#-------------------------------------------------------------------
=head2 www_view ( )

View file

@ -43,8 +43,36 @@ sub description {
#
#-------------------------------------------------------------------
#sub handler {
#}
sub handler {
my $self = shift;
### Add to group action
# If group is 'everyone', skip
unless ($self->{_product}->get('groupId') eq '7') {
my $g = WebGUI::Group->new($self->session,$self->{_product}->get('groupId'));
my $expiresOffset;
# Parse the value
if ($self->{_product}->get('groupExpiresOffset') =~ /^(\d+)month/i) {
$expiresOffset = $1 * 3600*24*30; # One month
} elsif ($self->{_product}->get('groupExpiresOffset') =~ /^(\d+)year/i) {
$expiresOffset = $1 * 3600*24*365; # One year
}
# Multiply by how many quantity we're purchasing
#!!! TODO !!! - handlers don't know how many we're purchasing
# If user has time left
my $remains = $g->userGroupExpireDate($self->session->user->userId);
if ($remains) {
# Add any remaining time to the offset
$expiresOffset += $remains - time();
}
# Add user to group
$g->addUsers([$self->session->user->userId],$expiresOffset);
}
}
#-------------------------------------------------------------------
sub id {

View file

@ -67,7 +67,7 @@ This package provides an object-oriented way of managing WebGUI groups and group
$arrayRef = $group->getAllUsers(); ##All users in all groups in this group
$boolean = $self->session->user->isInGroup($groupId);
$boolean = $group->userIsAdmin($userId,$groupId);
$epoch = $group->userGroupExpireDate($userId,$groupId);
$epoch = $group->userGroupExpireDate($userId,$date);
=head1 METHODS

View file

@ -398,7 +398,7 @@ sub www_checkoutSubmit {
foreach (@{$currentPurchase->{items}}) {
my $priceLineItem = ($_->{item}->{priceLineItem}) ? ($_->{item}->priceLineItem($_->{quantity},\@copyOfNormal)) : undef; # pass in the quantity and the normal items in the cart.
$session->errorHandler->warn("Price Line Item: $priceLineItem");
#$session->errorHandler->warn("Price Line Item: $priceLineItem");
$transaction->addItem($_->{item}, $_->{quantity},$priceLineItem);
# use the item plugin's lineItem method for price override
# situations.

View file

@ -151,66 +151,97 @@ sub www_editProduct {
$product = WebGUI::Product->new($session,$productId)->get;
}
$f = WebGUI::HTMLForm->new($session);
$f = WebGUI::TabForm->new($session);
$f->addTab("properties","Properties");
$f->addTab("actions","Actions");
$f->submit;
$f->hidden(
-name => 'op',
-value => 'editProductSave'
);
$f->hidden(
-name => 'productId',
-value => $productId
);
$f->text(
$f->hidden({
name => 'op',
value => 'editProductSave'
});
$f->hidden({
name => 'productId',
value => $productId
});
$f->getTab("properties")->text(
-name => 'title',
-label => $i18n->get('title'),
-hoverHelp => $i18n->get('title description'),
-value => $session->form->process("title") || $product->{title},
-maxlength => 255,
);
$f->textarea(
$f->getTab("properties")->textarea(
-name => 'description',
-label => $i18n->get('description'),
-hoverHelp => $i18n->get('description description'),
-value => $session->form->process("decsription") || $product->{description},
);
$f->float(
$f->getTab("properties")->float(
-name => 'price',
-label => $i18n->get('price'),
-hoverHelp => $i18n->get('price description'),
-value => $session->form->process("price") || $product->{price},
-maxlength => 13,
);
$f->float(
$f->getTab("properties")->float(
-name => 'weight',
-label => $i18n->get('weight'),
-hoverHelp => $i18n->get('weight description'),
-value => $session->form->process("weight") || $product->{weight},
-maxlength => 9,
);
$f->text(
$f->getTab("properties")->text(
-name => 'sku',
-label => $i18n->get('sku'),
-hoverHelp => $i18n->get('sku description'),
-value => $session->form->process("sku") || $product->{sku},
-maxlength => 64,
);
$f->template(
$f->getTab("properties")->template(
-name => 'templateId',
-label => $i18n->get('template'),
-hoverHelp => $i18n->get('template description'),
-value => $session->form->process("templateId") || $product->{templateId},
-namespace => 'Commerce/Product',
);
$f->text(
$f->getTab("properties")->text(
-name => 'skuTemplate',
-label => $i18n->get('sku template'),
-hoverHelp => $i18n->get('sku template description'),
-value => $session->form->process("skuTemplate") || $product->{skuTemplate},
-maxlength => 255,
);
$f->submit;
$f->getTab("actions")->group(
-name => 'groupId',
-label => $i18n->get('group id'),
-hoverHelp => $i18n->get('group id description'),
-value => $session->form->process("groupId") || $product->{groupId},
);
my %groupExpiresOffsetOptions;
tie %groupExpiresOffsetOptions, 'Tie::IxHash',
'1month' => $i18n->get("1 month"),
'6month' => $i18n->get("6 months"),
'1year' => $i18n->get("1 year"),
'2year' => $i18n->get("2 years"),
'3year' => $i18n->get("3 years"),
'5year' => $i18n->get("5 years"),
'10year' => $i18n->get("10 years"),
'1000year' => $i18n->get("lifetime"),
;
$f->getTab("actions")->selectBox(
-name => 'groupExpiresOffset',
-label => $i18n->get('group expires offset'),
-hoverHelp => $i18n->get('group expires offset description'),
-value => $session->form->process("groupExpiresOffset") || $product->{groupExpiresOffset},
-options => \%groupExpiresOffsetOptions,
-defaultValue => '1000year',
);
return _submenu($session,$f->print, 'edit product', 'edit product', 'ProductManager');
}
@ -251,6 +282,10 @@ sub www_editProductSave {
sku => $session->form->process("sku"),
templateId => $session->form->process("templateId"),
skuTemplate => $session->form->process("skuTemplate"),
groupId => $session->form->process('groupId'),
groupExpiresOffset => $session->form->process('groupExpiresOffset'),
});
return www_manageProduct($session, $product->get('productId'));

148
lib/WebGUI/Text.pm Normal file
View file

@ -0,0 +1,148 @@
package WebGUI::Text;
=head1 LEGAL
-------------------------------------------------------------------
WebGUI is Copyright 2001-2006 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 warnings;
use base 'Exporter';
our @EXPORT_OK = qw(
joinCSV splitCSV
);
our %EXPORT_TAGS = (
"csv" => [qw( joinCSV splitCSV )],
);
=head1 NAME
WebGUI::Text - Routines for manipulating text.
=head1 SYNOPSIS
use WebGUI::Text qw(:csv);
my $string = joinCSV(@array);
my @array = splitCSV($string);
=head1 DESCRIPTION
Some convenience routines that can be exported to work with text data.
=head1 METHODS
=cut
#-------------------------------------------------------------------
=head2 joinCSV ( @array )
Join an array of data together to create a properly formatted and escaped CSV
string according to the de-facto standard outlined by RFC 4180.
=cut
sub joinCSV {
my @input = @_;
my @fixed; # The properly escaped data
for my $i (@input) {
# Ignore all characters that aren't ASCII printable characters
$i =~ s/[^\x09\x20-\x7e]//g;
# All strings with these chars in them must be quoted
if ($i =~ /[",\n\t]/ || $i =~ /^\s|\s$/s) {
# " must be doubled ("")
$i =~ s/"/""/g;
$i = qq{"$i"};
}
push @fixed, $i;
}
return join ",",@fixed;
}
#-------------------------------------------------------------------
=head2 splitCSV ( $string )
Splits a CSV string and fixes any escaping done.
=cut
sub splitCSV {
my $s = shift;
# Split on ,
my @array = split /,/, $s;
for (my $i = 0; $i < @array; $i++) {
# Fix quoted strings being used to escape commas.
# If it begins with a " but doesn't end with an odd number of "
# shift, add to previous, and try again
if ($array[$i] =~ /^"/s && length(($array[$i] =~ m/("*)$/s)[0]) % 2 == 0 ) {
# If there are no more elements, this line is erroneous
if ($i+1 > @array) { warn "Error parsing CSV line."; return; }
$array[$i] .= ",".splice(@array,$i+1,1);
redo;
}
# Remove quotes on end of string
$array[$i] =~ s/^"|"$//sg;
# Fix doubled quotes
$array[$i] =~ s/""/"/g;
}
return @array;
}
=head1 BUGS
=over 4
=item *
splitCSV doesn't properly handle quoted fields with no text inside (...,"",...)
=back
=head1 SEE ALSO
=over 4
=item *
RFC 4180 (http://tools.ietf.org/html/rfc4180)
=back
=cut
1;

View file

@ -319,6 +319,59 @@ query, but will be prefixed with queryN where N goes from 2 to 5.</p>
<p>The prequery statements are seperated from each other by returns and cannot use placeholders. You can use macro's within the prequery statements, however. Please note that prequery statements are only visible in the query they belong to and that you can only use statements that are allowed by the database link.</p>|,
lastUpdated => 0,
},
'download type' => {
message => 'Download Type',
lastUpdated => 0,
},
'download type description' => {
message => "The type of download to create.",
lastUpdated => 0,
},
'download filename' => {
message => 'Download File Name',
lastUpdated => 0,
},
'download filename description' => {
message => "The filename of the file to download. If left blank, will autogenerate.",
lastUpdated => 0,
},
'download template' => {
message => "Download Template",
lastUpdated => 0,
},
'download template description' => {
message => "The template to use to generate the download file.",
lastUpdated => 0,
},
'download mimetype' => {
message => "Download Mime-Type",
lastUpdated => 0,
},
'download mimetype description' => {
message => "Mime-Type for the downloaded template.",
lastUpdated => 0,
},
'download usergroup' => {
message => "Download User Group",
lastUpdated => 0,
},
'download usergroup description' => {
message => "Group of users allowed to download the report.",
lastUpdated => 0,
},
};
1;

View file

@ -567,6 +567,68 @@ the form.<br />|,
message => q|Product Manager|,
lastUpdated => 1128919931,
},
'group id' => {
message => "Add to Group",
lastUpdated => 0,
context => "Label for add to group action",
},
'group id description' => {
message => "Add purchasers of this product to this group. Set to 'everyone' to disable.",
lastUpdated => 0,
context => "Hover help for add to group action",
},
'group expires offset' => {
message => "Group Expires Offset",
lastUpdated => 0,
context => "Label for group expires offset",
},
'group expires offset description' => {
message => "Length of time added to user's expiration from the above group each time this product is purchased.",
lastUpdated => 0,
context => "Hover help for group expires offset",
},
'6 months' => {
message => "6 months",
lastUpdated => 0,
context => "A time period for group expires offset",
},
'1 year' => {
message => "1 year",
lastUpdated => 0,
context => "A time period for group expires offset",
},
'2 years' => {
message => "2 years",
lastUpdated => 0,
context => "A time period for group expires offset",
},
'3 years' => {
message => "3 years",
lastUpdated => 0,
context => "A time period for group expires offset",
},
'5 years' => {
message => "5 years",
lastUpdated => 0,
context => "A time period for group expires offset",
},
'10 years' => {
message => "10 years",
lastUpdated => 0,
context => "A time period for group expires offset",
},
'lifetime' => {
message => "lifetime",
lastUpdated => 0,
context => "A time period for group expires offset",
},
};