1241 lines
44 KiB
Perl
1241 lines
44 KiB
Perl
package WebGUI::Asset::Wobject::Matrix;
|
|
|
|
use strict;
|
|
our $VERSION = "2.0.0";
|
|
|
|
#-------------------------------------------------------------------
|
|
# 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 Tie::IxHash;
|
|
use JSON;
|
|
use WebGUI::International;
|
|
use WebGUI::Utility;
|
|
use WebGUI::Asset::MatrixListing;
|
|
use base 'WebGUI::Asset::Wobject';
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head2 canAddMatrixListing ( )
|
|
|
|
Returns true if able to add MatrixListings.
|
|
|
|
=cut
|
|
|
|
sub canAddMatrixListing {
|
|
my $self = shift;
|
|
|
|
return 0 if $self->session->user->isVisitor;
|
|
|
|
return 1;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 definition ( )
|
|
|
|
defines wobject properties for Matrix instances.
|
|
|
|
=cut
|
|
|
|
sub definition {
|
|
my $class = shift;
|
|
my $session = shift;
|
|
my $definition = shift;
|
|
my $i18n = WebGUI::International->new($session, 'Asset_Matrix');
|
|
|
|
my %properties;
|
|
tie %properties, 'Tie::IxHash';
|
|
%properties = (
|
|
templateId =>{
|
|
fieldType =>"template",
|
|
defaultValue =>'matrixtmpl000000000001',
|
|
tab =>"display",
|
|
noFormPost =>0,
|
|
namespace =>"Matrix",
|
|
hoverHelp =>$i18n->get('template description'),
|
|
label =>$i18n->get('template label'),
|
|
},
|
|
searchTemplateId=>{
|
|
defaultValue =>"matrixtmpl000000000005",
|
|
fieldType =>"template",
|
|
tab =>"display",
|
|
namespace =>"Matrix/Search",
|
|
hoverHelp =>$i18n->get('search template description'),
|
|
label =>$i18n->get('search template label'),
|
|
},
|
|
detailTemplateId=>{
|
|
defaultValue =>"matrixtmpl000000000003",
|
|
fieldType =>"template",
|
|
tab =>"display",
|
|
namespace =>"Matrix/Detail",
|
|
hoverHelp =>$i18n->get('detail template description'),
|
|
label =>$i18n->get('detail template label'),
|
|
},
|
|
compareTemplateId=>{
|
|
defaultValue =>"matrixtmpl000000000002",
|
|
fieldType =>"template",
|
|
tab =>"display",
|
|
namespace =>"Matrix/Compare",
|
|
hoverHelp =>$i18n->get('compare template description'),
|
|
label =>$i18n->get('compare template label'),
|
|
},
|
|
editListingTemplateId=>{
|
|
defaultValue =>"matrixtmpl000000000004",
|
|
fieldType =>"template",
|
|
tab =>"display",
|
|
namespace =>"Matrix/EditListing",
|
|
hoverHelp =>$i18n->get('edit listing template description'),
|
|
label =>$i18n->get('edit listing template label'),
|
|
},
|
|
defaultSort=>{
|
|
fieldType =>"selectBox",
|
|
tab =>"display",
|
|
options =>{
|
|
score => $i18n->get('sort by score label'),
|
|
title => $i18n->get('sort alpha numeric label'),
|
|
lineage => $i18n->get('sort by asset rank label'),
|
|
lastUpdated => $i18n->get('sort by last updated label'),
|
|
},
|
|
defaultValue =>"score",
|
|
hoverHelp =>$i18n->get('default sort description'),
|
|
label =>$i18n->get('default sort label'),
|
|
},
|
|
compareColorNo=>{
|
|
fieldType =>"color",
|
|
tab =>"display",
|
|
defaultValue =>"#ffaaaa",
|
|
hoverHelp =>$i18n->get('compare color no description'),
|
|
label =>$i18n->get('compare color no label'),
|
|
},
|
|
compareColorLimited=>{
|
|
fieldType =>"color",
|
|
tab =>"display",
|
|
defaultValue =>"#ffffaa",
|
|
hoverHelp =>$i18n->get('compare color limited description'),
|
|
label =>$i18n->get('compare color limited label'),
|
|
},
|
|
compareColorCostsExtra=>{
|
|
fieldType =>"color",
|
|
tab =>"display",
|
|
defaultValue =>"#ffffaa",
|
|
hoverHelp =>$i18n->get('compare color costs extra description'),
|
|
label =>$i18n->get('compare color costs extra label'),
|
|
},
|
|
compareColorFreeAddOn=>{
|
|
fieldType =>"color",
|
|
tab =>"display",
|
|
defaultValue =>"#ffffaa",
|
|
hoverHelp =>$i18n->get('compare color free add on description'),
|
|
label =>$i18n->get('compare color free add on label'),
|
|
},
|
|
compareColorYes=>{
|
|
fieldType =>"color",
|
|
tab =>"display",
|
|
defaultValue =>"#aaffaa",
|
|
hoverHelp =>$i18n->get('compare color yes description'),
|
|
label =>$i18n->get('compare color yes label'),
|
|
},
|
|
categories=>{
|
|
fieldType =>"textarea",
|
|
tab =>"properties",
|
|
defaultValue =>$i18n->get('categories default value'),
|
|
hoverHelp =>$i18n->get('categories description'),
|
|
label =>$i18n->get('categories label'),
|
|
subtext =>$i18n->get('categories subtext'),
|
|
},
|
|
maxComparisons=>{
|
|
fieldType =>"integer",
|
|
tab =>"properties",
|
|
defaultValue =>25,
|
|
hoverHelp =>$i18n->get('max comparisons description'),
|
|
label =>$i18n->get('max comparisons label'),
|
|
},
|
|
maxComparisonsPrivileged=>{
|
|
fieldType =>"integer",
|
|
tab =>"properties",
|
|
defaultValue =>10,
|
|
hoverHelp =>$i18n->get('max comparisons privileged description'),
|
|
label =>$i18n->get('max comparisons privileged label'),
|
|
},
|
|
submissionApprovalWorkflowId=>{
|
|
fieldType =>"workflow",
|
|
tab =>"security",
|
|
type =>'WebGUI::VersionTag',
|
|
defaultValue =>"pbworkflow000000000003",
|
|
hoverHelp =>$i18n->get('submission approval workflow description'),
|
|
label =>$i18n->get('submission approval workflow label'),
|
|
},
|
|
ratingsDuration=>{
|
|
fieldType =>"interval",
|
|
tab =>"properties",
|
|
defaultValue =>7776000, # 3 months 3*30*24*60*60
|
|
hoverHelp =>$i18n->get('ratings duration description'),
|
|
label =>$i18n->get('ratings duration label'),
|
|
},
|
|
);
|
|
push(@{$definition}, {
|
|
assetName=>$i18n->get('assetName'),
|
|
icon=>'matrix.gif',
|
|
autoGenerateForms=>1,
|
|
tableName=>'Matrix',
|
|
className=>'WebGUI::Asset::Wobject::Matrix',
|
|
properties=>\%properties
|
|
});
|
|
return $class->SUPER::definition($session, $definition);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 deleteAttribute ( attributeId )
|
|
|
|
Deletes an attribute and listing data for this attribute from Collateral.
|
|
|
|
=head3 attributeId
|
|
|
|
The id of the attribute that should be deleted.
|
|
|
|
=cut
|
|
|
|
sub deleteAttribute {
|
|
|
|
my $self = shift;
|
|
my $attributeId = shift;
|
|
|
|
$self->deleteCollateral("Matrix_attribute","attributeId",$attributeId);
|
|
$self->session->db->write("delete from MatrixListing_attribute where attributeId=? and matrixId=?",
|
|
[$attributeId,$self->getId]);
|
|
|
|
# recalculate scores for MatrixListings
|
|
my @listings = @{ $self->getLineage(['descendants'], {
|
|
includeOnlyClasses => ['WebGUI::Asset::MatrixListing'],
|
|
returnObjects => 1,
|
|
}) };
|
|
foreach my $listing (@listings){
|
|
$listing->updateScore;
|
|
}
|
|
|
|
return undef;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 duplicate ( )
|
|
|
|
duplicates a Matrix.
|
|
|
|
=cut
|
|
|
|
sub duplicate {
|
|
my $self = shift;
|
|
my $newAsset = $self->SUPER::duplicate(@_);
|
|
return $newAsset;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 editAttributeSave ( attributeProperties )
|
|
|
|
Saves an attribute.
|
|
|
|
=head3 attributeProperties
|
|
|
|
A hashref containing the properties of the attribute.
|
|
|
|
=cut
|
|
|
|
sub editAttributeSave {
|
|
my $self = shift;
|
|
my $attributeProperties = shift;
|
|
my $session = $self->session;
|
|
my $form = $session->form;
|
|
|
|
return $session->privilege->insufficient() unless $self->canEdit;
|
|
|
|
my $attributeId = $self->setCollateral("Matrix_attribute","attributeId",$attributeProperties,0,1);
|
|
|
|
return $attributeId;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getAttribute ( attributeId )
|
|
|
|
Returns a hash reference of the properties of an attribute.
|
|
|
|
=head3 attributeId
|
|
|
|
The unique id of an attribute.
|
|
|
|
=cut
|
|
|
|
sub getAttribute {
|
|
my ($self, $attributeId) = @_;
|
|
return $self->session->db->quickHashRef("select * from Matrix_attribute where attributeId=?",[$attributeId]);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getCategories ( )
|
|
|
|
Returns the categories for this Matrix as a hashref.
|
|
|
|
=cut
|
|
|
|
sub getCategories {
|
|
my $self = shift;
|
|
my %categories;
|
|
tie %categories, 'Tie::IxHash';
|
|
|
|
my $categories = $self->getValue("categories");
|
|
$categories =~ s/\r//g;
|
|
chomp($categories);
|
|
|
|
my @categories = split(/\n/,$categories);
|
|
foreach my $category (@categories) {
|
|
$categories{$category} = $category;
|
|
}
|
|
return \%categories;
|
|
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getCompareColor ( )
|
|
|
|
Returns the compare color for a MatrixCompare value.
|
|
|
|
=head3 value
|
|
|
|
The value of a MatrixCompare form field.
|
|
|
|
=cut
|
|
|
|
sub getCompareColor {
|
|
|
|
my $self = shift;
|
|
my $value = shift;
|
|
|
|
if($value == 0){
|
|
return $self->get('compareColorNo');
|
|
}
|
|
elsif($value == 1){
|
|
return $self->get('compareColorLimited');
|
|
}
|
|
elsif($value == 2){
|
|
return $self->get('compareColorCostsExtra');
|
|
}
|
|
elsif($value == 3){
|
|
return $self->get('compareColorFreeAddOn');
|
|
}
|
|
elsif($value == 4){
|
|
return $self->get('compareColorYes');
|
|
}
|
|
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getCompareForm ( )
|
|
|
|
Returns the compare form.
|
|
|
|
=cut
|
|
|
|
sub getCompareForm {
|
|
my $self = shift;
|
|
|
|
my $form = WebGUI::Form::formHeader($self->session,{action=>$self->getUrl,extras=>'name="doCompare"'})
|
|
."<br />"
|
|
.WebGUI::Form::hidden($self->session, {
|
|
name=>"func",
|
|
value=>"compare"
|
|
})
|
|
.'<div id="compareForm"></div> '
|
|
."<br />"
|
|
.WebGUI::Form::formFooter($self->session);
|
|
|
|
my $maxComparisons;
|
|
if($self->session->user->isVisitor){
|
|
$maxComparisons = $self->get('maxComparisons');
|
|
}
|
|
else{
|
|
$maxComparisons = $self->get('maxComparisonsPrivileged');
|
|
}
|
|
$form .= "\n<script type='text/javascript'>\n".
|
|
'var maxComparisons = '.$maxComparisons.";\n".
|
|
"var matrixUrl = '".$self->getUrl."';\n".
|
|
"\n</script>\n";
|
|
return $form;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 getEditForm ( )
|
|
|
|
returns the tabform object that will be used in generating the edit page for Matrix.
|
|
|
|
=cut
|
|
|
|
sub getEditForm {
|
|
my $self = shift;
|
|
my $tabform = $self->SUPER::getEditForm();
|
|
return $tabform;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=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;
|
|
|
|
return undef;
|
|
}
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 purge ( )
|
|
|
|
removes collateral data associated with a Matrix when the system
|
|
purges it's data.
|
|
|
|
=cut
|
|
|
|
sub purge {
|
|
my $self = shift;
|
|
|
|
$self->session->db->write("delete from Matrix_attribute where assetId=?",[$self->getId]);
|
|
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 $db = $session->db;
|
|
|
|
# javascript and css files for compare form datatable
|
|
$self->session->style->setLink($self->session->url->extras('yui/build/datatable/assets/skins/sam/datatable.css'),
|
|
{type =>'text/css', rel=>'stylesheet'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/json/json-min.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/connection/connection-min.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/get/get-min.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/element/element-beta-min.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/datasource/datasource-min.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/datatable/datatable-min.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/button/button-min.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('wobject/Matrix/matrix.js'), {type =>
|
|
'text/javascript'});
|
|
|
|
my $var = $self->get;
|
|
$var->{isLoggedIn} = ($self->session->user->userId ne "1");
|
|
$var->{addMatrixListing_url} = $self->getUrl('func=add;class=WebGUI::Asset::MatrixListing');
|
|
$var->{compareForm} = $self->getCompareForm;
|
|
$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'], {
|
|
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 />";
|
|
}
|
|
|
|
# Get the MatrixListing with the most compares as an object using getLineage.
|
|
|
|
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 />";
|
|
}
|
|
|
|
# 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.
|
|
|
|
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} }, {
|
|
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 />";
|
|
|
|
|
|
# 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,
|
|
name => $pendingListing->get('title'),
|
|
});
|
|
}
|
|
|
|
# For each category, get the MatrixListings with the best ratings.
|
|
|
|
foreach my $category (keys %{$self->getCategories}) {
|
|
my $data;
|
|
my $sql = "
|
|
select
|
|
assetData.title as productName,
|
|
assetData.url,
|
|
rating.listingId,
|
|
rating.meanValue,
|
|
asset.parentId
|
|
from
|
|
MatrixListing_ratingSummary as rating
|
|
left join asset on (rating.listingId = asset.assetId)
|
|
left join assetData on assetData.assetId = rating.listingId
|
|
where
|
|
rating.category =?
|
|
and asset.parentId=?
|
|
and asset.state='published'
|
|
and assetData.revisionDate=(
|
|
select
|
|
max(revisionDate)
|
|
from
|
|
assetData
|
|
where
|
|
assetData.assetId=asset.assetId
|
|
and (status='approved' or status='archived')
|
|
)
|
|
group by
|
|
assetData.assetId
|
|
order by rating.meanValue ";
|
|
|
|
$data = $db->quickHashRef($sql." desc limit 1",[$category,$self->getId]);
|
|
push(@{ $var->{best_rating_loop} },{
|
|
url=>'/'.$data->{url},
|
|
category=>$category,
|
|
name=>$data->{productName},
|
|
mean=>$data->{meanValue},
|
|
median=>$data->{medianValue},
|
|
count=>$data->{countValue}
|
|
});
|
|
$data = $db->quickHashRef($sql." asc limit 1",[$category,$self->getId]);
|
|
push(@{ $var->{worst_rating_loop} },{
|
|
url=>'/'.$data->{url},
|
|
category=>$category,
|
|
name=>$data->{productName},
|
|
mean=>$data->{meanValue},
|
|
median=>$data->{medianValue},
|
|
count=>$data->{countValue}
|
|
});
|
|
}
|
|
|
|
$var->{listingCount} = scalar $db->buildArray("
|
|
select *
|
|
from asset, assetData
|
|
where asset.assetId=assetData.assetId
|
|
and asset.parentId=?
|
|
and asset.state='published'
|
|
and asset.className='WebGUI::Asset::MatrixListing'
|
|
and assetData.status='approved'
|
|
group by asset.assetId",
|
|
[$self->getId]);
|
|
|
|
return $self->processTemplate($var, undef, $self->{_viewTemplate});
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_compare ( )
|
|
|
|
Returns the compare screen
|
|
|
|
=head3 listingIds
|
|
|
|
An array of listingIds that should be selected in the compare form.
|
|
|
|
=cut
|
|
|
|
sub www_compare {
|
|
|
|
my $self = shift;
|
|
my $var = $self->get;
|
|
my @listingIds = @_;
|
|
my @responseFields;
|
|
|
|
unless (scalar(@listingIds)) {
|
|
@listingIds = $self->session->form->checkList("listingId");
|
|
}
|
|
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/yahoo/yahoo-min.js'),
|
|
{type => 'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/dom/dom-min.js'),
|
|
{type => 'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/event/event-min.js'),
|
|
{type => 'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/json/json-min.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/connection/connection-min.js'),
|
|
{type => 'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/get/get-min.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/element/element-beta-min.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/datasource/datasource-min.js'),
|
|
{type => 'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/datatable/datatable-min.js'),
|
|
{type =>'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/button/button-min.js'),
|
|
{type =>'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('wobject/Matrix/matrixCompareList.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('wobject/Matrix/matrix.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setLink($self->session->url->extras('yui/build/datatable/assets/skins/sam/datatable.css'),
|
|
{type =>'text/css', rel=>'stylesheet'});
|
|
$self->session->style->setScript($self->session->url->extras('hoverhelp.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setLink($self->session->url->extras('hoverhelp.css'),
|
|
{type =>'text/css', rel=>'stylesheet'});
|
|
|
|
my $maxComparisons;
|
|
if($self->session->user->isVisitor){
|
|
$maxComparisons = $self->get('maxComparisons');
|
|
}
|
|
else{
|
|
$maxComparisons = $self->get('maxComparisonsPrivileged');
|
|
}
|
|
|
|
foreach my $listingId (@listingIds){
|
|
my $listingId_safe = $listingId;
|
|
$listingId_safe =~ s/-/_____/g;
|
|
push(@responseFields, $listingId_safe, $listingId_safe."_compareColor");
|
|
}
|
|
|
|
$var->{javascript} = "<script type='text/javascript'>\n".
|
|
'var listingIds = new Array('.join(", ",map {'"'.$_.'"'} @listingIds).");\n".
|
|
'var responseFields = new Array("attributeId", "name", "description","fieldType", "checked", '.join(", ",map {'"'.$_.'"'} @responseFields).");\n".
|
|
"var maxComparisons = ".$maxComparisons.";\n".
|
|
"var matrixUrl = '".$self->getUrl."';\n".
|
|
"</script>";
|
|
|
|
return $self->processStyle($self->processTemplate($var,$self->get("compareTemplateId")));
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_deleteAttribute ( )
|
|
|
|
Deletes an Attribute, including listing data for this attribute.
|
|
|
|
=cut
|
|
|
|
sub www_deleteAttribute {
|
|
my $self = shift;
|
|
my $attributeId = $self->session->form->process("attributeId");
|
|
|
|
return $self->session->privilege->insufficient() unless $self->canEdit;
|
|
|
|
$self->deleteAttribute($attributeId);
|
|
|
|
return $self->www_listAttributes;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_deleteStickied ( )
|
|
|
|
Sets the sort scratch variable.
|
|
|
|
=cut
|
|
|
|
sub www_deleteStickied {
|
|
|
|
my $self = shift;
|
|
|
|
if(my $attributeId = $self->session->form->process("attributeId")){
|
|
$self->session->scratch->delete('stickied_'.$attributeId);
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_editAttribute ( )
|
|
|
|
Shows a form to edit or add an attribute.
|
|
|
|
=cut
|
|
|
|
sub www_editAttribute {
|
|
my $self = shift;
|
|
my $session = $self->session;
|
|
my ($attributeId, $attribute);
|
|
|
|
return $session->privilege->insufficient() unless $self->canEdit;
|
|
my $i18n = WebGUI::International->new($session, "Asset_Matrix");
|
|
|
|
$attributeId = $session->form->process("attributeId") || 'new';
|
|
|
|
unless($attributeId eq 'new'){
|
|
$attribute = $self->getAttribute($attributeId);
|
|
}
|
|
|
|
my $form = WebGUI::HTMLForm->new($self->session,-action=>$self->getUrl);
|
|
$form->hidden(
|
|
-name =>"func",
|
|
-value =>"editAttributeSave"
|
|
);
|
|
$form->hidden(
|
|
-name =>"attributeId",
|
|
-value =>$attributeId,
|
|
);
|
|
$form->text(
|
|
-name =>"name",
|
|
-value =>$attribute->{name},
|
|
-label =>$i18n->get('attribute name label'),
|
|
-hoverHelp =>$i18n->get('attribute name description'),
|
|
);
|
|
$form->textarea(
|
|
-name =>"description",
|
|
-value =>$attribute->{description},
|
|
-label =>$i18n->get('attribute description label'),
|
|
-hoverHelp =>$i18n->get('attribute description description'),
|
|
);
|
|
$form->matrixFieldType(
|
|
-name =>"fieldType",
|
|
-value =>$attribute->{fieldType},
|
|
-label =>$i18n->get('fieldType label'),
|
|
-hoverHelp =>$i18n->get('fieldType description'),
|
|
);
|
|
my $defaultValueForm = WebGUI::Form::Text($self->session, {
|
|
name=>"defaultValue",
|
|
value=>$attribute->{defaultValue},
|
|
resizable=>0,
|
|
});
|
|
my $optionsForm = WebGUI::Form::Textarea($self->session, {
|
|
name=>"options",
|
|
value=>$attribute->{options},
|
|
});
|
|
|
|
my $html = "\n<tr><td colspan='2'>\n";
|
|
$html .= "\t<div id='optionsAndDefaultValue_module'>\n";
|
|
$html .= "\t<div class='bd' style='padding:0px;'>\n";
|
|
$html .= "\t<table cellpadding='0' cellspacing='0' style='width: 100%;'>\n";
|
|
|
|
$html .= "\t<tr><td class='formDescription' valign='top' style='width:180px'>"
|
|
.$i18n->get('attribute defaultValue label')
|
|
."<div class='wg-hoverhelp'>".$i18n->get('attribute defaultValue description')."</div></td>"
|
|
."<td valign='top' class='tableData' style='padding-left:4px'>"
|
|
.$defaultValueForm."</td>"
|
|
."\t\n</tr>\n";
|
|
|
|
$html .= "\t<tr><td class='formDescription' valign='top' style='width:180px'>"
|
|
.$i18n->get('attribute options label')
|
|
."<div class='wg-hoverhelp'>".$i18n->get('attribute options description')."</div></td>"
|
|
."<td valign='top' class='tableData' style='padding-left:4px'>"
|
|
.$optionsForm."</td>"
|
|
."\t\n</tr>\n";
|
|
|
|
|
|
$html .= "\t</table>";
|
|
$html .= "\t\n</div>\t\n</div>\n";
|
|
$html .= "</td></tr>";
|
|
|
|
$html .= "<script type='text/javascript'>\n"
|
|
."var optionsAndDefaultValue_module = new YAHOO.widget.Module('optionsAndDefaultValue_module',"
|
|
."{visible:false});\n"
|
|
."optionsAndDefaultValue_module.render();\n"
|
|
."YAHOO.util.Event.onContentReady('fieldType_formId', checkFieldType);\n"
|
|
."YAHOO.util.Event.addListener('fieldType_formId', 'change', checkFieldType);\n"
|
|
."var hasOptions = {'SelectBox': true,'Combo': true};\n"
|
|
."function checkFieldType(){\n"
|
|
." if (this.value in hasOptions){\n"
|
|
." optionsAndDefaultValue_module.show();\n"
|
|
." }else{\n"
|
|
." optionsAndDefaultValue_module.hide();\n"
|
|
." }\n"
|
|
."}\n"
|
|
."</script>\n";
|
|
|
|
$form->raw($html);
|
|
|
|
$form->selectBox(
|
|
-name =>"category",
|
|
-value =>[$attribute->{category}],
|
|
-label =>$i18n->get('category label'),
|
|
-hoverHelp =>$i18n->get('category description'),
|
|
-options =>$self->getCategories,
|
|
);
|
|
$form->submit;
|
|
return $self->getAdminConsole->render($form->print, $i18n->get('edit attribute title'));
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_editAttributeSave ( )
|
|
|
|
Processes and saves an attribute.
|
|
|
|
=cut
|
|
|
|
sub www_editAttributeSave {
|
|
my $self = shift;
|
|
my $session = $self->session;
|
|
my $form = $session->form;
|
|
|
|
return $session->privilege->insufficient() unless $self->canEdit;
|
|
|
|
my $attributeProperties = {
|
|
attributeId =>$form->process("attributeId") || 'new',
|
|
assetId =>$self->getId,
|
|
name =>$form->process('name'),
|
|
description =>$form->process('description'),
|
|
fieldType =>$form->process('fieldType'),
|
|
options =>$form->process('options'),
|
|
defaultValue =>$form->process('defaultValue'),
|
|
category =>$form->process('category'),
|
|
};
|
|
|
|
$self->editAttributeSave($attributeProperties);
|
|
|
|
return $self->www_listAttributes;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_exportAttributes ( )
|
|
|
|
Exports search attributes as csv.
|
|
|
|
=cut
|
|
|
|
sub www_exportAttributes {
|
|
my $self = shift;
|
|
my $session = $self->session;
|
|
my $output = WebGUI::Text::joinCSV("name","description","category");
|
|
|
|
my $attributes = $session->db->read("select name, description, category
|
|
from Matrix_attribute where assetId = ? order by category, name",[$self->getId]);
|
|
|
|
while (my $attribute = $attributes->hashRef) {
|
|
$output .= "\n".WebGUI::Text::joinCSV($attribute->{name},$attribute->{description},$attribute->{category});
|
|
}
|
|
|
|
my $fileName = "export_matrix_attributes.csv";
|
|
$self->session->http->setFilename($fileName,"application/octet-stream");
|
|
$self->session->http->sendHeader;
|
|
return $output;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_getCompareFormData ( )
|
|
|
|
Returns the compare form data as JSON.
|
|
|
|
=head3 sort
|
|
|
|
The criterium by which the listings should be sorted.
|
|
|
|
=cut
|
|
|
|
sub www_getCompareFormData {
|
|
|
|
my $self = shift;
|
|
my $session = $self->session;
|
|
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");
|
|
|
|
$self->session->http->setMimeType("application/json");
|
|
|
|
my $sql = "
|
|
select
|
|
assetData.title,
|
|
assetData.url,
|
|
listing.assetId,
|
|
listing.views,
|
|
listing.compares,
|
|
listing.clicks,
|
|
listing.lastUpdated
|
|
from asset
|
|
left join assetData using(assetId)
|
|
left join MatrixListing as listing on listing.assetId = assetData.assetId and listing.revisionDate =
|
|
assetData.revisionDate
|
|
where
|
|
asset.parentId=?
|
|
and asset.state='published'
|
|
and asset.className='WebGUI::Asset::MatrixListing'
|
|
and assetData.revisionDate = (SELECT max(revisionDate) from assetData where assetId=asset.assetId and status='approved')
|
|
and status='approved'
|
|
order by ".$sort.$sortDirection;
|
|
|
|
@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")){
|
|
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",
|
|
[$result->{assetId}],'attributeId');
|
|
PARAM: foreach my $param (@searchParams_sorted) {
|
|
my $fieldType = $matrixListing_attributes->{$param->{attributeId}}->{fieldType};
|
|
my $listingValue = $matrixListing_attributes->{$param->{attributeId}}->{value};
|
|
if(($fieldType eq 'MatrixCompare') && ($listingValue < $param->{value})){
|
|
$result->{checked} = '';
|
|
last PARAM;
|
|
}
|
|
elsif(($fieldType ne 'MatrixCompare' && $fieldType ne '') && ($param->{value} ne $listingValue)){
|
|
$result->{checked} = '';
|
|
last PARAM;
|
|
}
|
|
else{
|
|
$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});
|
|
}
|
|
my $jsonOutput;
|
|
$jsonOutput->{ResultSet} = {Result=>\@results};
|
|
|
|
my $encodedOutput = JSON->new->encode($jsonOutput);
|
|
return $encodedOutput;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_getCompareListData ( )
|
|
|
|
Returns the compare list data as JSON.
|
|
|
|
=head3 listingIds
|
|
|
|
An array of listingIds that should be shown in the compare list datatable.
|
|
|
|
=cut
|
|
|
|
sub www_getCompareListData {
|
|
|
|
my $self = shift;
|
|
my @listingIds = @_;
|
|
my $session = $self->session;
|
|
my $i18n = WebGUI::International->new($session,'Asset_Matrix');
|
|
my (@results,@columnDefs);
|
|
|
|
unless (scalar(@listingIds)) {
|
|
@listingIds = $self->session->form->checkList("listingId");
|
|
}
|
|
|
|
foreach my $listingId (@listingIds){
|
|
$listingId =~ s/_____/-/g;
|
|
my $listing = WebGUI::Asset::MatrixListing->new($session,$listingId);
|
|
$listing->incrementCounter("compares");
|
|
my $listingId_safe = $listingId;
|
|
$listingId_safe =~ s/-/_____/g;
|
|
push(@columnDefs,{
|
|
key =>$listingId_safe,
|
|
label =>$listing->get('title').' '.$listing->get('version'),
|
|
formatter =>"formatColors",
|
|
url =>$listing->getUrl,
|
|
lastUpdated =>$session->datetime->epochToHuman( $listing->get('revisonDate'),"%z" ),
|
|
});
|
|
}
|
|
push(@results,{name=>$i18n->get('last updated label'),fieldType=>'lastUpdated'});
|
|
|
|
my $jsonOutput;
|
|
$jsonOutput->{ColumnDefs} = \@columnDefs;
|
|
|
|
foreach my $category (keys %{$self->getCategories}) {
|
|
push(@results,{name=>$category,fieldType=>'category'});
|
|
my $fields = " a.name, a.fieldType, a.attributeId, a.description ";
|
|
my $from = "from Matrix_attribute a";
|
|
my $tableCount = "b";
|
|
my $where;
|
|
foreach my $listingId (@listingIds) {
|
|
my $listingId_safe = $listingId;
|
|
$listingId_safe =~ s/-/_____/g;
|
|
$fields .= ", ".$tableCount.".value as `$listingId_safe`";
|
|
$from .= " left join MatrixListing_attribute ".$tableCount." on a.attributeId=".$tableCount.".attributeId";
|
|
$where .= "and ".$tableCount.".matrixListingId=?";
|
|
$tableCount++;
|
|
}
|
|
push(@results, @{ $self->session->db->buildArrayRefOfHashRefs(
|
|
"select $fields $from where a.category=? and a.assetId=? ".$where." order by a.name",
|
|
[$category,$self->getId,@listingIds]
|
|
) });
|
|
}
|
|
|
|
foreach my $result (@results){
|
|
if($result->{fieldType} eq 'category'){
|
|
# Row starting with a category label shows the listing name in each column
|
|
foreach my $columnDef (@columnDefs) {
|
|
$result->{$columnDef->{key}} = $columnDef->{label};
|
|
}
|
|
}
|
|
elsif($result->{fieldType} eq 'lastUpdated'){
|
|
foreach my $columnDef (@columnDefs) {
|
|
$result->{$columnDef->{key}} = $columnDef->{lastUpdated};
|
|
}
|
|
}
|
|
else{
|
|
foreach my $listingId (@listingIds) {
|
|
$result->{attributeId} =~ s/-/_____/g;
|
|
my $listingId_safe = $listingId;
|
|
$listingId_safe =~ s/-/_____/g;
|
|
if ($result->{fieldType} eq 'MatrixCompare'){
|
|
my $originalValue = $result->{$listingId_safe};
|
|
$result->{$listingId_safe.'_compareColor'} = $self->getCompareColor($result->{$listingId_safe});
|
|
$result->{$listingId_safe} = WebGUI::Form::MatrixCompare->new( $self->session,
|
|
{ value=>$result->{$listingId_safe} },defaultValue=>0)->getValueAsHtml;
|
|
}
|
|
if($session->scratch->get('stickied_'.$result->{attributeId})){
|
|
# $self->session->errorHandler->warn("found checked stickie: ".$result->{attributeId});
|
|
$result->{checked} = 'checked';
|
|
}
|
|
else{
|
|
$result->{checked} = '';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$jsonOutput->{ResultSet} = {Result=>\@results};
|
|
$session->http->setMimeType("application/json");
|
|
|
|
return JSON->new->encode($jsonOutput);
|
|
}
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_listAttributes ( )
|
|
|
|
Lists all attributes of this Matrix.
|
|
|
|
=cut
|
|
|
|
sub www_listAttributes {
|
|
my $self = shift;
|
|
my $session = $self->session;
|
|
|
|
return $session->privilege->insufficient() unless($self->canEdit);
|
|
|
|
my $i18n = WebGUI::International->new($session,'Asset_Matrix');
|
|
my $output = "<br /><a href='".$self->getUrl("func=editAttribute;attributeId=new")."'>"
|
|
.$i18n->get('add attribute label')."</a><br /><br />";
|
|
|
|
my $attributes = $session->db->read("select attributeId, name from Matrix_attribute where assetId=? order by name"
|
|
,[$self->getId]);
|
|
while (my $attribute = $attributes->hashRef) {
|
|
$output .= $session->icon->delete("func=deleteAttribute;attributeId=".$attribute->{attributeId}
|
|
, $self->getUrl,$i18n->get("delete attribute confirm message"))
|
|
.$session->icon->edit("func=editAttribute;attributeId=".$attribute->{attributeId})
|
|
.' '.$attribute->{name}."<br />\n";
|
|
}
|
|
return $self->getAdminConsole->render($output, $i18n->get('list attributes title'));
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_search ( )
|
|
|
|
Returns the search screen.
|
|
|
|
=cut
|
|
|
|
sub www_search {
|
|
|
|
my $self = shift;
|
|
my $var = $self->get;
|
|
|
|
$var->{compareForm} = $self->getCompareForm;
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/yahoo/yahoo-min.js'),
|
|
{type => 'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/dom/dom-min.js'),
|
|
{type => 'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/event/event-min.js'),
|
|
{type => 'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/json/json-min.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/connection/connection-min.js'),
|
|
{type => 'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/get/get-min.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/element/element-beta-min.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/datasource/datasource-min.js'),
|
|
{type => 'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/datatable/datatable-min.js'),
|
|
{type =>'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('yui/build/button/button-min.js'),
|
|
{type =>'text/javascript'});
|
|
$self->session->style->setScript($self->session->url->extras('wobject/Matrix/matrixSearch.js'), {type =>
|
|
'text/javascript'});
|
|
$self->session->style->setLink($self->session->url->extras('yui/build/datatable/assets/skins/sam/datatable.css'),
|
|
{type =>'text/css', rel=>'stylesheet'});
|
|
|
|
foreach my $category (keys %{$self->getCategories}) {
|
|
my $attributes;
|
|
my @attribute_loop;
|
|
my $categoryLoopName = $self->session->url->urlize($category)."_loop";
|
|
$attributes = $self->session->db->read("select * from Matrix_attribute where category =? and assetId = ?",
|
|
[$category,$self->getId]);
|
|
while (my $attribute = $attributes->hashRef) {
|
|
$attribute->{label} = $attribute->{name};
|
|
$attribute->{id} = $attribute->{attributeId};
|
|
$attribute->{id} =~ s/-/_____/g;
|
|
$attribute->{extras} = " class='attributeSelect'";
|
|
if($attribute->{fieldType} eq 'Combo'){
|
|
$attribute->{fieldType} = 'SelectBox';
|
|
}
|
|
if($attribute->{fieldType} eq 'SelectBox'){
|
|
$attribute->{options} = "blank\n".$attribute->{options};
|
|
$attribute->{value} = 'blank';
|
|
}
|
|
$attribute->{form} = WebGUI::Form::DynamicField->new($self->session,%{$attribute})->toHtml;
|
|
push(@attribute_loop,$attribute);
|
|
}
|
|
$var->{$categoryLoopName} = \@attribute_loop;
|
|
push(@{$var->{category_loop}},{
|
|
categoryLabel => $category,
|
|
attribute_loop => \@attribute_loop,
|
|
});
|
|
}
|
|
|
|
return $self->processStyle($self->processTemplate($var,$self->get("searchTemplateId")));
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_setSort ( )
|
|
|
|
Sets the sort scratch variable.
|
|
|
|
=cut
|
|
|
|
sub www_setSort {
|
|
|
|
my $self = shift;
|
|
|
|
if(my $sort = $self->session->form->process("sort")){
|
|
$self->session->scratch->set('matrixSort',$sort);
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_setStickied ( )
|
|
|
|
Sets the stickied scratch variable.
|
|
|
|
=cut
|
|
|
|
sub www_setStickied {
|
|
|
|
my $self = shift;
|
|
|
|
if(my $attributeId = $self->session->form->process("attributeId")){
|
|
$self->session->scratch->set('stickied_'.$attributeId,1);
|
|
}
|
|
return undef;
|
|
}
|
|
|
|
1;
|