559 lines
17 KiB
Perl
559 lines
17 KiB
Perl
package WebGUI::Asset::Wobject::Poll;
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
# 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
|
|
#-------------------------------------------------------------------
|
|
|
|
use strict;
|
|
use List::Util;
|
|
use WebGUI::Form;
|
|
use WebGUI::International;
|
|
use WebGUI::SQL;
|
|
use WebGUI::User;
|
|
use WebGUI::Utility;
|
|
use WebGUI::Asset::Wobject;
|
|
use WebGUI::Image::Graph;
|
|
use WebGUI::Storage;
|
|
use JSON;
|
|
|
|
our @ISA = qw(WebGUI::Asset::Wobject);
|
|
|
|
#-------------------------------------------------------------------
|
|
sub _hasVoted {
|
|
my $self = shift;
|
|
my ($hasVoted) = $self->session->db->quickArray("select count(*) from Poll_answer
|
|
where assetId=".$self->session->db->quote($self->getId)." and ((userId=".$self->session->db->quote($self->session->user->userId)."
|
|
and userId<>'1') or (userId=".$self->session->db->quote($self->session->user->userId)." and ipAddress='".$self->session->env->getIp."'))");
|
|
return $hasVoted;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
sub definition {
|
|
my $class = shift;
|
|
my $session = shift;
|
|
my $definition = shift;
|
|
my $i18n = WebGUI::International->new($session,"Asset_Poll");
|
|
push(@{$definition}, {
|
|
assetName=>$i18n->get('assetName'),
|
|
tableName=>'Poll',
|
|
icon=>'poll.gif',
|
|
className=>'WebGUI::Asset::Wobject::Poll',
|
|
autoGenerateForms=>1,
|
|
properties=>{
|
|
templateId =>{
|
|
tab => 'display',
|
|
fieldType => "template",
|
|
defaultValue => 'PBtmpl0000000000000055',
|
|
label => $i18n->get(73),
|
|
hoverHelp => $i18n->get('73 description'),
|
|
namespace => "Poll",
|
|
},
|
|
active=>{
|
|
tab => 'properties',
|
|
fieldType => "yesNo",
|
|
defaultValue => 1,
|
|
label => $i18n->get(3),
|
|
hoverHelp => $i18n->get('3 description'),
|
|
},
|
|
karmaPerVote=>{
|
|
fieldType=>"integer",
|
|
defaultValue=>0,
|
|
autoGenerate=>0,
|
|
},
|
|
graphWidth=>{
|
|
fieldType=>"integer",
|
|
defaultValue=>150,
|
|
autoGenerate=>0,
|
|
},
|
|
voteGroup=>{
|
|
tab => 'security',
|
|
fieldType => "group",
|
|
defaultValue => 7,
|
|
label => $i18n->get(4),
|
|
hoverHelp => $i18n->get('4 description'),
|
|
},
|
|
question=>{
|
|
tab => 'properties',
|
|
fieldType => "text",
|
|
defaultValue => undef,
|
|
label => $i18n->get(6),
|
|
hoverHelp => $i18n->get('6 description'),
|
|
},
|
|
randomizeAnswers=>{
|
|
tab => 'properties',
|
|
fieldType => "yesNo",
|
|
defaultValue => 1,
|
|
label => $i18n->get(72),
|
|
hoverHelp => $i18n->get('72 description'),
|
|
},
|
|
a1=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a2=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a3=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a4=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a5=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a6=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a7=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a8=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a9=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a10=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a11=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a12=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a13=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a14=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a15=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a16=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a17=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a18=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a19=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
a20=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef
|
|
},
|
|
graphConfiguration=>{
|
|
fieldType=>"hidden",
|
|
defaultValue=>undef,
|
|
},
|
|
generateGraph => {
|
|
fieldType => "yesNo",
|
|
defaultValue => 0,
|
|
autoGenerate => 0,
|
|
},
|
|
}
|
|
});
|
|
return $class->SUPER::definition($session, $definition);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 duplicate
|
|
|
|
Extend the base method to handle copying Poll answer data.
|
|
|
|
=cut
|
|
|
|
sub duplicate {
|
|
my $self = shift;
|
|
my $newAsset = $self->SUPER::duplicate(@_);
|
|
my $sth = $self->session->db->read("select * from Poll_answer where assetId=?", [$self->getId]);
|
|
while (my $data = $sth->hashRef) {
|
|
$newAsset->setVote($data->{answer}, $data->{userId}, $data->{ipAddress});
|
|
}
|
|
$sth->finish;
|
|
return $newAsset;
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head2 freezeGraphConfig
|
|
|
|
Serializes graph configuration. Returns a scalar containing the serialized
|
|
structure.
|
|
|
|
=cut
|
|
|
|
sub freezeGraphConfig {
|
|
my $self = shift;
|
|
my $obj = shift;
|
|
|
|
return JSON::to_json($obj);
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getEditForm
|
|
|
|
Extend the base class to handle the answers and graphing plugins.
|
|
|
|
=cut
|
|
|
|
##TODO: Pull out all form elements which can come from the definition sub
|
|
##and only have hand code in here.
|
|
|
|
sub getEditForm {
|
|
my $self = shift;
|
|
my $tabform = $self->SUPER::getEditForm;
|
|
my $i18n = WebGUI::International->new($self->session,"Asset_Poll");
|
|
my ($i, $answers);
|
|
for ($i=1; $i<=20; $i++) {
|
|
if ($self->get('a'.$i) =~ /./) {
|
|
$answers .= $self->getValue("a".$i)."\n";
|
|
}
|
|
}
|
|
if ($self->session->setting->get("useKarma")) {
|
|
$tabform->getTab("properties")->integer(
|
|
-name=>"karmaPerVote",
|
|
-label=>$i18n->get(20),
|
|
-hoverHelp=>$i18n->get('20 description'),
|
|
-value=>$self->getValue("karmaPerVote")
|
|
);
|
|
} else {
|
|
$tabform->getTab("properties")->hidden(
|
|
-name=>"karmaPerVote",
|
|
-value=>$self->getValue("karmaPerVote")
|
|
);
|
|
}
|
|
$tabform->getTab("display")->integer(
|
|
-name=>"graphWidth",
|
|
-label=>$i18n->get(5),
|
|
-hoverHelp=>$i18n->get('5 description'),
|
|
-value=>$self->getValue("graphWidth")
|
|
);
|
|
$tabform->getTab("properties")->textarea(
|
|
-name=>"answers",
|
|
-label=>$i18n->get(7),
|
|
-hoverHelp=>$i18n->get('7 description'),
|
|
-subtext=>('<span class="formSubtext"><br />'.$i18n->get(8).'</span>'),
|
|
-value=>$answers
|
|
);
|
|
$tabform->getTab("properties")->yesNo(
|
|
-name=>"resetVotes",
|
|
-label=>$i18n->get(10),
|
|
-hoverHelp=>$i18n->get('10 description')
|
|
) if $self->session->form->process("func") ne 'add';
|
|
|
|
|
|
if (WebGUI::Image::Graph->getPluginList($self->session)) {
|
|
my $config = $self->getGraphConfig;
|
|
|
|
$tabform->addTab('graph', $i18n->get('Graphing','Image_Graph'));
|
|
$tabform->getTab('graph')->yesNo(
|
|
-name => 'generateGraph',
|
|
-label => $i18n->get('generate graph'),
|
|
-hoverHelp => $i18n->get('generate graph description'),
|
|
-value => $self->getValue('generateGraph'),
|
|
);
|
|
$tabform->getTab('graph')->raw(WebGUI::Image::Graph->getGraphingTab($self->session, $config));
|
|
}
|
|
|
|
return $tabform;
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head2 getGraphConfig
|
|
|
|
Gets and thaws the graph configuration. Returns a reference to the original
|
|
data structure.
|
|
|
|
=cut
|
|
|
|
sub getGraphConfig {
|
|
my $self = shift;
|
|
my $config = $self->get("graphConfiguration");
|
|
|
|
return undef unless $config;
|
|
return $self->thawGraphConfig($config);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 indexContent ( )
|
|
|
|
Indexing question and answers. See WebGUI::Asset::indexContent() for additonal details.
|
|
|
|
=cut
|
|
|
|
sub indexContent {
|
|
my $self = shift;
|
|
my $indexer = $self->SUPER::indexContent;
|
|
$indexer->addKeywords($self->get("question")." ".$self->get("answers"));
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 prepareView ( )
|
|
|
|
See WebGUI::Asset::prepareView() for details.
|
|
|
|
=cut
|
|
|
|
sub prepareView {
|
|
my $self = shift;
|
|
$self->SUPER::prepareView();
|
|
my $template = WebGUI::Asset::Template->new($self->session, $self->get("templateId"));
|
|
if (!$template) {
|
|
WebGUI::Error::ObjectNotFound::Template->throw(
|
|
error => qq{Template not found},
|
|
templateId => $self->get("templateId"),
|
|
assetId => $self->getId,
|
|
);
|
|
}
|
|
$template->prepare($self->getMetaDataAsTemplateVariables);
|
|
$self->{_viewTemplate} = $template;
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 processPropertiesFromFormPost
|
|
|
|
Extend the base method to handle the answers and the Graphing plugin.
|
|
|
|
=cut
|
|
|
|
sub processPropertiesFromFormPost {
|
|
my $self = shift;
|
|
$self->SUPER::processPropertiesFromFormPost;
|
|
my $property = {};
|
|
my $answers = $self->session->form->process("answers");
|
|
$answers =~ s{\r}{}xmsg;
|
|
my @answer = split("\n",$answers);
|
|
for (my $i=1; $i<=20; $i++) {
|
|
$property->{'a'.$i} = $answer[($i-1)] || "";
|
|
}
|
|
|
|
if (WebGUI::Image::Graph->getPluginList($self->session)) {
|
|
my $graph = WebGUI::Image::Graph->processConfigurationForm($self->session);
|
|
$self->setGraphConfig( $graph->getConfiguration );
|
|
}
|
|
|
|
$self->update($property);
|
|
$self->session->db->write("delete from Poll_answer where assetId=".$self->session->db->quote($self->getId)) if ($self->session->form->process("resetVotes"));
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 purge
|
|
|
|
Extend the base method to handle Poll answers.
|
|
|
|
=cut
|
|
|
|
sub purge {
|
|
my $self = shift;
|
|
$self->session->db->write("delete from Poll_answer where assetId=".$self->session->db->quote($self->getId));
|
|
$self->SUPER::purge();
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head2 setGraphConfig
|
|
|
|
Freezes and stores the configuration for the graphing of this poll.
|
|
|
|
=cut
|
|
|
|
sub setGraphConfig {
|
|
my $self = shift;
|
|
my $obj = shift;
|
|
|
|
$self->update({
|
|
graphConfiguration => $self->freezeGraphConfig($obj),
|
|
});
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 setVote ($answer, $userId, $ip)
|
|
|
|
Accumulates a vote into the database so that it can be counted.
|
|
|
|
=head3 $answer
|
|
|
|
The answer selected by the user.
|
|
|
|
=head3 $userid
|
|
|
|
The userId of the person who voted.
|
|
|
|
=head3 $ip
|
|
|
|
The IP address of the user who voted.
|
|
|
|
=cut
|
|
|
|
sub setVote {
|
|
my $self = shift;
|
|
my $answer = shift;
|
|
my $userId = shift;
|
|
my $ip = shift;
|
|
$self->session->db->write("insert into Poll_answer (assetId, answer, userId, ipAddress) values (?,?,?,?)",
|
|
[$self->getId, $answer, $userId, $ip] );
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head2 thawGraphConfig
|
|
|
|
Deserializes the graph configuration and returns the data structure.
|
|
|
|
=cut
|
|
|
|
sub thawGraphConfig {
|
|
my $self = shift;
|
|
my $string = shift;
|
|
|
|
return unless $string;
|
|
return JSON::from_json($string);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 view
|
|
|
|
Generate the poll results with graph if configured to do so. Display the form
|
|
for the user to vote.
|
|
|
|
=cut
|
|
|
|
sub view {
|
|
my $self = shift;
|
|
my (%var, $answer, @answers, $showPoll, $f, @dataset, @labels);
|
|
$var{question} = $self->get("question");
|
|
if ($self->get("active") eq "0") {
|
|
$showPoll = 0;
|
|
} elsif ($self->session->user->isInGroup($self->get("voteGroup"))) {
|
|
if ($self->_hasVoted()) {
|
|
$showPoll = 0;
|
|
} else {
|
|
$showPoll = 1;
|
|
}
|
|
} else {
|
|
$showPoll = 0;
|
|
}
|
|
$var{canVote} = $showPoll;
|
|
my ($totalResponses) = $self->session->db->quickArray("select count(*) from Poll_answer where assetId=".$self->session->db->quote($self->getId));
|
|
my $i18n = WebGUI::International->new($self->session,"Asset_Poll");
|
|
$var{"responses.label"} = $i18n->get(12);
|
|
$var{"responses.total"} = $totalResponses;
|
|
$var{"form.start"} = WebGUI::Form::formHeader($self->session,{action=>$self->getUrl});
|
|
$var{"form.start"} .= WebGUI::Form::hidden($self->session,{name=>'func',value=>'vote'});
|
|
$var{"form.submit"} = WebGUI::Form::submit($self->session,{value=>$i18n->get(11)});
|
|
$var{"form.end"} = WebGUI::Form::formFooter($self->session,);
|
|
$totalResponses = 1 if ($totalResponses < 1);
|
|
for (my $i=1; $i<=20; $i++) {
|
|
if ($self->get('a'.$i) =~ /./) {
|
|
my ($tally) = $self->session->db->quickArray("select count(*) from Poll_answer where answer='a"
|
|
.$i."' and assetId=".$self->session->db->quote($self->getId)." group by answer");
|
|
push(@answers,{
|
|
"answer.form"=>WebGUI::Form::radio($self->session,{name=>"answer",value=>"a".$i}),
|
|
"answer.text"=>$self->get('a'.$i),
|
|
"answer.graphWidth"=>round($self->get("graphWidth")*$tally/$totalResponses),
|
|
"answer.number"=>$i,
|
|
"answer.percent"=>round(100*$tally/$totalResponses),
|
|
"answer.total"=>($tally+0)
|
|
});
|
|
push(@dataset, ($tally+0));
|
|
push(@labels, $self->get('a'.$i));
|
|
}
|
|
}
|
|
@answers = List::Util::shuffle(@answers) if ($self->get("randomizeAnswers"));
|
|
$var{answer_loop} = \@answers;
|
|
|
|
if ($self->getValue('generateGraph')) {
|
|
my $config = $self->getGraphConfig;
|
|
if ($config) {
|
|
my $graph = WebGUI::Image::Graph->loadByConfiguration($self->session, $config);
|
|
$graph->addDataset(\@dataset);
|
|
$graph->setLabels(\@labels);
|
|
|
|
$graph->draw;
|
|
|
|
my $storage = WebGUI::Storage->createTemp($self->session);
|
|
my $filename = 'poll'.$self->session->id->generate.".png";
|
|
$graph->saveToStorageLocation($storage, $filename);
|
|
|
|
$var{graphUrl} = $storage->getUrl($filename);
|
|
$var{hasImageGraph} = 1;
|
|
} else {
|
|
$self->session->errorHandler->error('The graph configuration hash of the Poll ('.$self->getUrl.') is corrupt.');
|
|
}
|
|
}
|
|
|
|
return $self->processTemplate(\%var,undef,$self->{_viewTemplate});
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_vote
|
|
|
|
Web method for the user to add their vote. If so configured, gives karma
|
|
to the user.
|
|
|
|
=cut
|
|
|
|
sub www_vote {
|
|
my $self = shift;
|
|
my $u;
|
|
if ($self->session->form->process("answer") ne "" && $self->session->user->isInGroup($self->get("voteGroup")) && !($self->_hasVoted())) {
|
|
$self->setVote($self->session->form->process("answer"),$self->session->user->userId,$self->session->env->getIp);
|
|
if ($self->session->setting->get("useKarma")) {
|
|
$self->session->user->karma($self->get("karmaPerVote"),"Poll (".$self->getId.")","Voted on this poll.");
|
|
}
|
|
$self->getContainer->purgeCache;
|
|
}
|
|
|
|
return $self->session->asset($self->getContainer)->www_view;
|
|
}
|
|
|
|
|
|
|
|
1;
|
|
|