package WebGUI::Asset::Wobject::Matrix;
use strict;
use Tie::IxHash;
use WebGUI::Form;
use WebGUI::HTMLForm;
use WebGUI::Cache;
use WebGUI::Mail::Send;
use WebGUI::SQL;
use WebGUI::Storage::Image;
use WebGUI::User;
use WebGUI::Utility;
use WebGUI::Inbox;
use WebGUI::Asset::Wobject;
use WebGUI::Asset::Wobject::Collaboration;
our @ISA = qw(WebGUI::Asset::Wobject);
#-------------------------------------------------------------------
sub definition {
my $class = shift;
my $session = shift;
my $definition = shift;
my $i18n = WebGUI::International->new($session,"Asset_Matrix");
push(@{$definition}, {
icon=>'matrix.gif',
tableName=>'Matrix',
className=>'WebGUI::Asset::Wobject::Matrix',
assetName=>$i18n->get('assetName'),
properties=>{
visitorCacheTimeout => {
tab => "display",
fieldType => "interval",
defaultValue => 3600,
uiLevel => 8,
label => $i18n->get("visitor cache timeout"),
hoverHelp => $i18n->get("visitor cache timeout help")
},
categories=>{
defaultValue=>"Features\nBenefits",
fieldType=>"textarea"
},
maxComparisons=>{
defaultValue=>10,
fieldName=>"integer"
},
templateId=>{
defaultValue=>"matrixtmpl000000000001",
fieldType=>"template"
},
searchTemplateId=>{
defaultValue=>"matrixtmpl000000000005",
fieldType=>"template"
},
detailTemplateId=>{
defaultValue=>"matrixtmpl000000000003",
fieldType=>"template"
},
ratingDetailTemplateId=>{
defaultValue=>"matrixtmpl000000000004",
fieldType=>"template"
},
compareTemplateId=>{
defaultValue=>"matrixtmpl000000000002",
fieldType=>"template"
},
privilegedGroup=>{
defaultValue=>'2',
fieldType=>"group",
},
groupToRate=>{
defaultValue=>'2',
fieldType=>"group",
},
groupToAdd=>{
defaultValue=>'2',
fieldType=>"group",
},
maxComparisonsPrivileged=>{
defaultValue=>10,
fieldType=>"integer",
},
ratingTimeout=>{
defaultValue=>60*60*24*365,
fieldType=>"interval"
},
ratingTimeoutPrivileged=>{
defaultValue=>60*60*24*365,
fieldType=>"interval"
}
}
});
return $class->SUPER::definition($session, $definition);
}
#-------------------------------------------------------------------
sub duplicate {
# Buggo: how do we duplicate these?
return undef;
}
#-------------------------------------------------------------------
# Too much data to keep track of modification dates, always assume new data
sub getContentLastModified {
return time();
}
#-------------------------------------------------------------------
sub formatURL {
my $self = shift;
my $func = shift;
my $listingId = shift;
my $url = $self->getUrl("func=".$func.";listingId=".$listingId);
return $url;
}
#-------------------------------------------------------------------
sub getCategories {
my $self = shift;
my $cat = $self->getValue("categories");
$cat =~ s/\r//g;
chomp($cat);
my @categories = split(/\n/,$cat);
return @categories;
}
#-------------------------------------------------------------------
sub getCompareForm {
my $self = shift;
my @ids = @_;
my $form = WebGUI::Form::formHeader($self->session,{action=>$self->getUrl})
.WebGUI::Form::submit($self->session, {
value=>"compare"
})
."
"
."
"
.WebGUI::Form::hidden($self->session, {
name=>"func",
value=>"compare"
})
.WebGUI::Form::checkList($self->session, {
name=>"listingId",
vertical=>1,
value=>\@ids,
options=>$self->session->db->buildHashRef("select listingId, concat('getUrl("func=viewDetail").";listingId=',listingId,'\\\">', productName,'') from Matrix_listing
where assetId=".$self->session->db->quote($self->getId)." and status='approved' order by productName")
})
."
"
.WebGUI::Form::submit($self->session,{
value=>"compare"
})
.WebGUI::Form::formFooter($self->session);
return $form;
}
#-------------------------------------------------------------------
sub hasRated {
my $self = shift;
my $listingId = shift;
return 1 unless ($self->session->user->isInGroup($self->get("groupToRate")));
my $ratingTimeout = $self->session->user->isInGroup($self->get("privilegedGroup")) ? $self->get("ratingTimeoutPrivileged") : $self->get("ratingTimeout");
my ($hasRated) = $self->session->db->quickArray("select count(*) from Matrix_rating where
((userId=".$self->session->db->quote($self->session->user->userId)." and userId<>'1') or (userId='1' and ipAddress=".$self->session->db->quote($self->session->env->get("HTTP_X_FORWARDED_FOR")).")) and
listingId=".$self->session->db->quote($listingId)." and timeStamp>".($self->session->datetime->time()-$ratingTimeout));
return $hasRated;
}
#-------------------------------------------------------------------
sub incrementCounter {
my $self = shift;
my $listingId = shift;
my $counter = shift;
my ($lastIp) = $self->session->db->quickArray("select ".$counter."LastIp from Matrix_listing where listingId = ".$self->session->db->quote($listingId));
unless ($lastIp eq $self->session->env->get("HTTP_X_FORWARDED_FOR")) {
$self->session->db->write("update Matrix_listing set $counter=$counter+1, ".$counter."LastIp=".$self->session->db->quote($self->session->env->get("HTTP_X_FORWARDED_FOR"))." where listingId=".$self->session->db->quote($listingId));
}
}
#-------------------------------------------------------------------
=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"));
$template->prepare;
$self->{_viewTemplate} = $template;
}
#-------------------------------------------------------------------
sub purge {
my $self = shift;
$self->session->db->write("delete from Matrix_listing where assetId=".$self->session->db->quote($self->getId));
$self->session->db->write("delete from Matrix_listingData where assetId=".$self->session->db->quote($self->getId));
$self->session->db->write("delete from Matrix_field where assetId=".$self->session->db->quote($self->getId));
$self->session->db->write("delete from Matrix_rating where assetId=".$self->session->db->quote($self->getId));
$self->session->db->write("delete from Matrix_ratingSummary where assetId=".$self->session->db->quote($self->getId));
$self->SUPER::purge;
}
#-------------------------------------------------------------------
=head2 purgeCache ( )
See WebGUI::Asset::purgeCache() for details.
=cut
sub purgeCache {
my $self = shift;
WebGUI::Cache->new($self->session,"view_".$self->getId)->delete;
$self->SUPER::purgeCache;
}
#-------------------------------------------------------------------
sub setRatings {
my $self = shift;
my $listingId = shift;
my $ratings = shift;
foreach my $category ($self->getCategories) {
if ($ratings->{$category}) {
$self->session->db->write("insert into Matrix_rating (userId, category, rating, timeStamp, listingId,ipAddress, assetId) values (
".$self->session->db->quote($self->session->user->userId).", ".$self->session->db->quote($category).", ".$self->session->db->quote($ratings->{$category}).", ".$self->session->datetime->time()
.", ".$self->session->db->quote($listingId).", ".$self->session->db->quote($self->session->env->get("HTTP_X_FORWARDED_FOR")).",".$self->session->db->quote($self->getId).")");
}
my $sql = "from Matrix_rating where listingId=".$self->session->db->quote($listingId)." and category=".$self->session->db->quote($category);
my ($sum) = $self->session->db->quickArray("select sum(rating) $sql");
my ($count) = $self->session->db->quickArray("select count(*) $sql");
my $half = round($count/2);
my $mean = $sum / ($count || 1);
my ($median) = $self->session->db->quickArray("select rating $sql limit $half,$half");
$self->session->db->write("replace into Matrix_ratingSummary (listingId, category, meanValue, medianValue, countValue,assetId) values (
".$self->session->db->quote($listingId).", ".$self->session->db->quote($category).", $mean, ".$self->session->db->quote($median).", $count, ".$self->session->db->quote($self->getId).")");
}
}
#-------------------------------------------------------------------
sub www_approveListing {
my $self = shift;
return $self->session->privilege->insufficient() unless($self->canEdit);
my $listing = $self->session->db->getRow("Matrix_listing","listingId",$self->session->form->process("listingId"));
$self->session->db->write("update Matrix_listing set status='approved' where listingId=".$self->session->db->quote($self->session->form->process("listingId")));
my $inbox = WebGUI::Inbox->new($self->session);
$inbox->addMessage({
subject=>"New Listing Approved",
message=>"Your new listing, ".$listing->{productName}.", has been approved.",
status=>'completed',
userId=>$listing->{maintainerId}
});
my $message = $inbox->getMessage($listing->{approvalMessageId});
if (defined $message) {
$message->setCompleted;
}
return $self->www_viewDetail;
}
#-------------------------------------------------------------------
sub www_click {
my $self = shift;
$self->incrementCounter($self->session->form->process("listingId"),"clicks");
my $listing = $self->session->db->getRow("Matrix_listing","listingId",$self->session->form->process("listingId"));
if ($self->session->form->process("m")) {
$self->session->http->setRedirect($listing->{manufacturerUrl});
}
else {
$self->session->http->setRedirect($listing->{productUrl});
}
return undef;
}
#-------------------------------------------------------------------
sub www_compare {
my $self = shift;
my @cmsList = @_;
unless (scalar(@cmsList)) {
@cmsList = $self->session->form->checkList("listingId");
}
my ($style, $url) = ($self->session->style, $self->session->url);
my ( %var, @prodcol, @datecol);
my $max = $self->session->user->isInGroup($self->get("privilegedGroup")) ? $self->get("maxComparisonsPrivileged") : $self->get("maxComparisons");
$var{isTooMany} = (scalar(@cmsList)>$max);
$var{isTooFew} = (scalar(@cmsList)<2);
$var{'compare.form'} = $self->getCompareForm(@cmsList);
$var{'isLoggedIn'} = ($self->session->user->userId ne "1");
if ($var{isTooMany} || $var{isTooFew}) {
return $self->processStyle($self->processTemplate(\%var,$self->get("compareTemplateId")));
}
foreach my $cms (@cmsList) {
$self->incrementCounter($cms,"compares");
my $data = $self->session->db->quickHashRef("select listingId, productName, versionNumber, lastUpdated
from Matrix_listing where listingId=".$self->session->db->quote($cms));
push(@prodcol, {
name=>$data->{productName} || "__untitled__",
version=>$data->{versionNumber},
url=>$self->formatURL("viewDetail",$cms)
});
push(@datecol, {
lastUpdated=>$self->session->datetime->epochToHuman($data->{lastUpdated},"%z")
});
}
my $i18n = WebGUI::International->new($self->session,'Asset_Matrix');
my %goodBad = (
"No" => $i18n->get("no"),
"Yes" => $i18n->get("yes"),
"Free Add On" => $i18n->get("free"),
"Costs Extra" => $i18n->get("extra"),
"Limited" => $i18n->get("limited"),
);
$var{product_loop} = \@prodcol;
$var{lastupdated_loop} = \@datecol;
my @categoryloop;
foreach my $category ($self->getCategories()) {
my @rowloop;
my $select = "select a.fieldType, a.label, a.description";
my $from = "from Matrix_field a";
my $tableCount = "b";
foreach my $cms (@cmsList) {
$select .= ", ".$tableCount.".value";
$from .= " left join Matrix_listingData ".$tableCount." on a.fieldId="
.$tableCount.".fieldId and ".$tableCount.".listingId=".$self->session->db->quote($cms);
$tableCount++;
}
my $sth = $self->session->db->read("$select $from where a.category=".$self->session->db->quote($category)." and a.assetId=".$self->session->db->quote($self->getId)." order by a.label");
while (my @row = $sth->array) {
my @columnloop;
my $first = 1;
my $type = shift @row;
foreach my $value (@row) {
my $desc = "";
if ($first) {
$desc = $row[1];
shift(@row);
$first = 0;
}
elsif ($type eq 'goodBad') {
$value = $goodBad{$value};
}
my $class = lc($value);
$class =~ s/\s/_/g;
$class =~ s/\W//g;
push(@columnloop,{
value=>$value,
class=>$class,
description=>$desc
});
}
push(@rowloop,{
column_loop=>\@columnloop
});
}
$sth->finish;
push(@categoryloop,{
category=>$category,
columnCount=>$#cmsList+2,
row_loop=>\@rowloop
});
}
$var{category_loop} = \@categoryloop;
return $self->processStyle($self->processTemplate(\%var,$self->get("compareTemplateId")));
}
#-------------------------------------------------------------------
sub www_copy {
my $self = shift;
my $i18n = WebGUI::International->new($self->session,'Asset_Matrix');
return $i18n->get('no copy');
}
#-------------------------------------------------------------------
sub www_deleteField {
my $self = shift;
my $id = $self->session->form->param("fieldId");
$self->session->db->write("delete from Matrix_field where fieldId=?",[$id]);
$self->session->db->write("delete from Matrix_listingData where fieldId=?",[$id]);
$self->www_listFields();
}
#-------------------------------------------------------------------
sub www_deleteListing {
my $self = shift;
my $i18n = WebGUI::International->new($self->session,'Asset_Matrix');
my $output = sprintf $i18n->get('delete listing confirmation'),
$self->getUrl("func=deleteListingConfirm;listingId=".$self->session->form->process("listingId")),
$self->formatURL("viewDetail",$self->session->form->process("listingId"));
return $self->processStyle($output);
}
#-------------------------------------------------------------------
sub www_deleteListingConfirm {
my $self = shift;
return $self->session->privilege->insufficient() unless($self->canEdit);
my $listing = $self->session->db->getRow("Matrix_listing","listingId",$self->session->form->process("listingId"));
WebGUI::Asset::Wobject::Collaboration->new($self->session, $listing->{forumId})->purge;
$self->session->db->write("delete from Matrix_listing where listingId=".$self->session->db->quote($self->session->form->process("listingId")));
$self->session->db->write("delete from Matrix_listingData where listingId=".$self->session->db->quote($self->session->form->process("listingId")));
$self->session->db->write("delete from Matrix_rating where listingId=".$self->session->db->quote($self->session->form->process("listingId")));
$self->session->db->write("delete from Matrix_ratingSummary where listingId=".$self->session->db->quote($self->session->form->process("listingId")));
my $inbox = WebGUI::Inbox->new($self->session);
$inbox->addMessage({
status=>'completed',
subject=>"Listing Deleted",
message=>"Your listing, ".$listing->{productName}.", has been deleted from the matrix.",
userId=>$listing->{maintainerId}
});
my $message = $inbox->getMessage($listing->{approvalMessageId});
if (defined $message) {
$message->setCompleted;
}
return "";
}
#-------------------------------------------------------------------
sub getEditForm {
my $self = shift;
my $tabform = $self->SUPER::getEditForm();
my $i18n = WebGUI::International->new($self->session,'Asset_Matrix');
$tabform->getTab("display")->interval(
-name=>"visitorCacheTimeout",
-label=>$i18n->get('visitor cache timeout'),
-hoverHelp=>$i18n->get('visitor cache timeout help'),
-value=>$self->getValue('visitorCacheTimeout'),
-uiLevel=>8,
-defaultValue=>3600
);
$tabform->getTab("properties")->textarea(
-name=>"categories",
-label=>$i18n->get('categories'),
-hoverHelp=>$i18n->get('categories description'),
-value=>$self->getValue("categories"),
-subtext=>$i18n->get('categories subtext'),
);
$tabform->getTab("properties")->integer(
-name=>"maxComparisons",
-label=>$i18n->get("max comparisons"),
-hoverHelp=>$i18n->get("max comparisons description"),
-value=>$self->getValue("maxComparisons")
);
$tabform->getTab("properties")->integer(
-name=>"maxComparisonsPrivileged",
-label=>$i18n->get("max comparisons privileged"),
-hoverHelp=>$i18n->get("max comparisons privileged description"),
-value=>$self->getValue("maxComparisonsPrivileged")
);
$tabform->getTab("properties")->interval(
-name=>"ratingTimeout",
-label=>$i18n->get("rating timeout"),
-hoverHelp=>$i18n->get("rating timeout description"),
-value=>$self->getValue("ratingTimeout")
);
$tabform->getTab("properties")->interval(
-name=>"ratingTimeoutPrivileged",
-label=>$i18n->get("rating timeout privileged"),
-hoverHelp=>$i18n->get("rating timeout privileged description"),
-value=>$self->getValue("ratingTimeoutPrivileged")
);
$tabform->getTab("security")->group(
-name=>"groupToAdd",
-label=>$i18n->get("group to add"),
-hoverHelp=>$i18n->get("group to add description"),
-value=>[$self->getValue("groupToAdd")]
);
$tabform->getTab("security")->group(
-name=>"privilegedGroup",
-label=>$i18n->get("privileged group"),
-hoverHelp=>$i18n->get("privileged group description"),
-value=>[$self->getValue("privilegedGroup")]
);
$tabform->getTab("security")->group(
-name=>"groupToRate",
-label=>$i18n->get("rating group"),
-hoverHelp=>$i18n->get("rating group description"),
-value=>[$self->getValue("groupToRate")]
);
$tabform->getTab("display")->template(
-name=>"templateId",
-value=>$self->getValue("templateId"),
-label=>$i18n->get("main template"),
-hoverHelp=>$i18n->get("main template description"),
-namespace=>"Matrix"
);
$tabform->getTab("display")->template(
-name=>"detailTemplateId",
-value=>$self->getValue("detailTemplateId"),
-label=>$i18n->get("detail template"),
-hoverHelp=>$i18n->get("detail template description"),
-namespace=>"Matrix/Detail"
);
$tabform->getTab("display")->template(
-name=>"ratingDetailTemplateId",
-value=>$self->getValue("ratingDetailTemplateId"),
-label=>$i18n->get("rating detail template"),
-hoverHelp=>$i18n->get("rating detail template description"),
-namespace=>"Matrix/RatingDetail"
);
$tabform->getTab("display")->template(
-name=>"searchTemplateId",
-value=>$self->getValue("searchTemplateId"),
-label=>$i18n->get("search template"),
-hoverHelp=>$i18n->get("search template description"),
-namespace=>"Matrix/Search"
);
$tabform->getTab("display")->template(
-name=>"compareTemplateId",
-value=>$self->getValue("compareTemplateId"),
-label=>$i18n->get("compare template"),
-hoverHelp=>$i18n->get("compare template description"),
-namespace=>"Matrix/Compare"
);
return $tabform;
}
#-------------------------------------------------------------------
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_Wobject');
my $addEdit = ($self->session->form->process("func") eq 'add') ? $i18n->get('add') : $i18n->get('edit');
return $self->getAdminConsole->render($self->getEditForm->print, $self->addEditLabel);
}
#-------------------------------------------------------------------
=head2 www_deleteImage ( )
Deletes and attached file.
=cut
sub www_deleteImage {
my $self = shift;
my $listing = $self->session->db->getRow("Matrix_listing","listingId",$self->session->form->process("listingId"));
my $i18n = WebGUI::International->new($self->session,'Asset_Matrix');
return $i18n->get('no edit rights') unless ($self->session->user->userId eq $listing->{maintainerId} || $self->canEdit);
if ($listing->{storageId} ne "") {
my $storage = WebGUI::Storage::Image->get($self->session, $listing->{storageId});
$storage->delete;
}
return $self->www_editListing($listing, $i18n);
}
#-------------------------------------------------------------------
sub www_editListing {
my $self = shift;
my $listing= shift || $self->session->db->getRow("Matrix_listing","listingId",$self->session->form->process("listingId"));
my $i18n = shift || WebGUI::International->new($self->session,'Asset_Matrix');
return $i18n->get('no edit rights') unless (($self->session->form->process("listingId") eq "new" && $self->session->user->isInGroup($self->get("groupToAdd"))) || $self->session->user->userId eq $listing->{maintainerId} || $self->canEdit);
my $f = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl);
$f->hidden(
-name=>"func",
-value=>"editListingSave"
);
$f->hidden(
-name=>"listingId",
-value=>$self->session->form->process("listingId")
);
$f->text(
-name=>"productName",
-value=>$listing->{productName} || 'Undefined',
-label=>$i18n->get('product name'),
-hoverHelp=>$i18n->get('product name description'),
-maxLength=>25
);
$f->text(
-name=>"versionNumber",
-value=>$listing->{versionNumber},
-label=>$i18n->get('version number'),
-hoverHelp=>$i18n->get('version number description'),
);
$f->url(
-name=>"productUrl",
-value=>$listing->{productUrl},
-label=>$i18n->get('product url'),
-hoverHelp=>$i18n->get('product url description'),
);
$f->image(
name=>"screenshot",
label=>$i18n->get("screenshot"),
value=>$listing->{storageId},
hoverHelp=>$i18n->get("screenshot help"),
deleteFileUrl=>$self->getUrl("func=deleteImage;listingId=".$listing->{listingId}.";filename=")
);
$f->text(
-name=>"manufacturerName",
-value=>$listing->{manufacturerName},
-label=>$i18n->get('manufacturer name'),
-hoverHelp=>$i18n->get('manufacturer name description'),
);
$f->url(
-name=>"manufacturerUrl",
-value=>$listing->{manufacturerUrl},
-label=>$i18n->get('manufacturer url'),
);
$f->textarea(
-name=>"description",
-value=>$listing->{description},
-label=>$i18n->get('description'),
);
if ($self->canEdit) {
$f->user(
name=>"maintainerId",
value=>$listing->{maintainerId},
label=>$i18n->get('listing maintainer'),
hoverHelp=>$i18n->get('listing maintainer description'),
);
}
my %goodBad = (
"No" => $i18n->get("no"),
"Yes" => $i18n->get("yes"),
"Free Add On" => $i18n->get("free"),
"Costs Extra" => $i18n->get("extra"),
"Limited" => $i18n->get("limited"),
);
foreach my $category ($self->getCategories()) {
$f->raw('
| Mean | Median | Count | |
|---|---|---|---|
| '.$category.' | '.$mean.' | '.$median.' | '.$count.' |