Rough conversion of Comments and Installable to Moose.

This commit is contained in:
Colin Kuskie 2010-03-03 19:22:13 -08:00
parent a37b1c725b
commit 2b39e16cc8
2 changed files with 20 additions and 41 deletions

View file

@ -1,363 +0,0 @@
package WebGUI::AssetAspect::Comments;
=head1 LEGAL
-------------------------------------------------------------------
WebGUI is Copyright 2001-2009 Plain Black Corporation.
-------------------------------------------------------------------
Please read the legal notices (docs/legal.txt) and the license
(docs/license.txt) that came with this distribution before using
this software.
-------------------------------------------------------------------
http://www.plainblack.com info@plainblack.com
-------------------------------------------------------------------
=cut
use strict;
use Class::C3;
use JSON;
use Tie::IxHash;
use WebGUI::Exception;
use WebGUI::Form;
use WebGUI::HTML;
use WebGUI::Utility;
=head1 NAME
Package WebGUI::AssetAspect::Comments
=head1 DESCRIPTION
This is an aspect which makes adding comments to existing assets trivial.
=head1 SYNOPSIS
use Class::C3;
use base qw(WebGUI::AssetAspect::Comments WebGUI::Asset);
And then where-ever you would call $self->SUPER::someMethodName call $self->next::method instead.
=head1 METHODS
These methods are available from this class:
=cut
#-------------------------------------------------------------------
=head2 addComment ( comment [, rating, user ] )
Posts a comment.
=head3 comment
A string that acts as a comment from a user.
=head3 rating
Defaults to 0. An integer between 0 and 5 inclusive. 0 represents N/A, 1 represents a negative rating, 3 represents a neutral rating, and 5 represents a positive rating.
=head3 user
Defaults to the current user. A WebGUI::User object.
=cut
sub addComment {
my ($self, $comment, $rating, $user) = @_;
my $session = $self->session;
$user ||= $session->user;
$rating ||= 0;
# add the new comment to the list of comments
my $comments = $self->get('comments');
push @$comments, {
id => $session->id->generate,
alias => $user->profileField('alias'),
userId => $user->userId,
comment => $comment,
rating => $rating,
date => time(),
ip => $session->var->get('lastIP'),
};
# calculate average
my $sum = 0;
my $count = 0;
foreach my $comment (@$comments) {
next unless $comment->{rating} > 0; # skip n/a ratings
$count++;
$sum += $comment->{rating};
}
my $average = 0;
if ($count > 0) {
$average = $sum/$count;
}
# update the database
$self->update({comments=>$comments, averageCommentRating=>$average});
# add karma
if ($session->setting->get('useKarma')) {
unless ($user->isVisitor) {
$user->karma($self->getKarmaAmountPerComment, $self->getId, 'Left comment for '.$self->getName.' '.$self->getTitle);
}
}
}
#-------------------------------------------------------------------
=head2 canComment ()
Returns a boolean indicating whether the current user can post a comment.
=cut
sub canComment {
my $self = shift;
return $self->session->user->isInGroup($self->getGroupToComment) || $self->canEdit;
}
#-------------------------------------------------------------------
=head2 definition
Extends the definition to add the comments and averageCommentRating fields.
=cut
sub definition {
my $class = shift;
my $session = shift;
my $definition = shift;
my %properties;
tie %properties, 'Tie::IxHash';
%properties = (
comments => {
noFormPost => 1,
fieldType => "hidden",
defaultValue => [],
},
averageCommentRating => {
noFormPost => 1,
fieldType => "hidden",
defaultValue => 0,
},
);
push(@{$definition}, {
autoGenerateForms => 1,
tableName => 'assetAspectComments',
className => 'WebGUI::Asset::Sku::BazaarItem',
properties => \%properties
});
return $class->next::method($session, $definition);
}
#-------------------------------------------------------------------
=head2 deleteComment ( id )
Deletes a comment.
=head3 id
The GUID for the comment to delete.
=cut
sub deleteComment {
my ($self, $id) = @_;
my $session = $self->session;
# remove the comment from the list of comments and calculate the average
my $comments = $self->get('comments');
my @updatedComments;
my $sum = 0;
my $count = 0;
my $userId;
foreach my $comment (@$comments) {
if ($comment->{id} eq $id) {
$userId = $comment->{userId};
next;
}
push @updatedComments, $comment;
next unless $comment->{rating} > 0; # skip n/a ratings
$count++;
$sum += $comment->{rating};
}
# update the database
my $average = 0;
if ($count > 0) {
$average = $sum/$count;
}
$self->update({comments=>\@updatedComments, averageCommentRating=>$average});
# remove karma
if ($session->setting->get('useKarma')) {
if (defined $userId) {
my $user = WebGUI::User->new($session, $userId);
unless ($user->isVisitor) {
$user->karma(($self->getKarmaAmountPerComment * -1), $self->getId, 'Deleted comment for '.$self->getName.' '.$self->getTitle);
}
}
}
}
#-------------------------------------------------------------------
=head2 get ()
See SUPER::get(). Extends the get() method to automatically decode the comments field into a Perl hash structure.
=cut
sub get {
my $self = shift;
my $param = shift;
if ($param eq 'comments') {
return JSON->new->decode($self->next::method('comments')||'[]');
}
return $self->next::method($param, @_);
}
#-------------------------------------------------------------------
=head2 getAverageCommentRatingIcon ()
Returns the HTML needed to render the average rating icon.
=cut
sub getAverageCommentRatingIcon {
my $self = shift;
return q{<img src="}.$self->session->url->extras('form/CommentRating/'.round($self->get('averageCommentRating'),0).'.png').q{" style="vertical-align: middle;" alt="}.$self->get('averageCommentRating').q{" />};
}
#-------------------------------------------------------------------
=head2 getFormattedComments ()
Returns an HTML string listing the comments so far and the leave a comment form if the user canComment().
=cut
sub getFormattedComments {
my $self = shift;
my $session = $self->session;
my $url = $session->url;
my $out = '<div class="assetAspectComments">';
my $canEdit = $self->canEdit;
my $comments = $self->get('comments');
foreach my $comment (@$comments) {
$out .= q{<div class="assetAspectComment"><img src="}.$url->extras('form/CommentRating/'.$comment->{rating}.'.png').q{" alt="}.$comment->{rating}.q{" style="vertical-align: bottom;" />};
if ($canEdit) {
$out .= q{ <a href="}.$self->getUrl("func=deleteComment;commentId=".$comment->{id}).q{">[X]</a> };
}
$out .= q{<b>}.$comment->{alias}.q{:</b> "}.WebGUI::HTML::format($comment->{comment},'text').q{"</div>};
}
if ($self->canComment) {
$out .= '<div class="assetAspectCommentForm">';
$out .= WebGUI::Form::formHeader($session, {action=>$self->getUrl});
$out .= WebGUI::Form::hidden($session, {name=>"func",value=>"addComment"});
$out .= WebGUI::Form::textarea($session, {name=>"comment"});
$out .= WebGUI::Form::commentRating($session, {name=>"rating"});
$out .= WebGUI::Form::submit($session);
$out .= WebGUI::Form::formFooter($session);
$out .= '</div>';
}
$out .= '</div>';
return $out;
}
#-------------------------------------------------------------------
=head2 getGroupToComment ()
Returns '2' aka Registered Users. However, should be overridden by subclasses that wish to make this a settable property.
=cut
sub getGroupToComment {
return '2';
}
#-------------------------------------------------------------------
=head2 getKarmaAmountPerComment ()
Returns 3. However, should be overridden by subclasses that wish to make this a settable property.
=cut
sub getKarmaAmountPerComment {
return 3;
}
#-------------------------------------------------------------------
=head2 update ()
See SUPER::update(). Extends the update() method to encode the comments field into something storable in the database.
=cut
sub update {
my $self = shift;
my $properties = shift;
if (exists $properties->{comments}) {
my $comments = $properties->{comments};
if (ref $comments ne 'ARRAY') {
$comments = eval{JSON->new->decode($comments)};
if (WebGUI::Error->caught || ref $comments ne 'ARRAY') {
$comments = [];
}
}
$properties->{comments} = JSON->new->encode($comments);
}
$self->next::method($properties, @_);
}
#-------------------------------------------------------------------
=head2 www_addComment ()
Posts a comment after verifying the user's privileges.
=cut
sub www_addComment {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient() unless ($self->canComment);
my $form = $session->form;
my $comment = $form->get('comment','textarea');
WebGUI::Macro::negate(\$comment);
if ($comment ne '') {
$self->addComment($comment, $form->get('rating','commentRating'));
}
$self->www_view;
}
#-------------------------------------------------------------------
=head2 www_deleteComment ()
Removes a comment.
=cut
sub www_deleteComment {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient() unless ($self->canEdit);
$self->deleteComment($session->form->get('commentId'));
$self->www_view;
}
1;

View file

@ -1,214 +0,0 @@
package WebGUI::AssetAspect::Installable;
use strict;
use Class::C3;
use WebGUI::Asset;
use WebGUI::Form::DynamicField;
=head1 NAME
WebGUI::AssetAspect::Installable -- Make your asset installable
=head1 SYNOPSIS
package WebGUI::Asset::MyAsset;
use base ( 'WebGUI::AssetAspect::Installable', 'WebGUI::Asset' );
# Override the install method to install collateral tables
sub install {
my $class = shift;
my $session = shift;
$self->next::method( $session );
}
# Override the uninstall method to remove collateral tables
sub uninstall {
my $class = shift;
my $session = shift;
$self->next::method( $session );
}
=head1 DESCRIPTION
This aspect adds installing and uninstalling to your asset class.
For most purposes, just inheriting from this aspect will suffice.
If you need to install collateral information or otherwise, override the
C<install> method, but make sure to call the superclass before you try
anything else.
=head1 METHODS
=cut
#----------------------------------------------------------------------------
=head2 install ( session )
Install the asset. C<session> is a WebGUI::Session object from the site to
install the asset into.
=cut
sub install {
my $class = shift;
my $session = shift;
### Install the first member of the definition
my $definition = $class->definition($session);
my $installDef = shift @{$definition};
# Make the table according to WebGUI::Form::Control's databaseFieldType
my $sql
= q{CREATE TABLE `}
. $installDef->{tableName} . q{` ( }
. q{`assetId` CHAR(22) BINARY NOT NULL, }
. q{`revisionDate` BIGINT NOT NULL, };
for my $column ( keys %{ $installDef->{properties} } ) {
my $control = WebGUI::Form::DynamicField->new( $session, %{ $installDef->{properties}->{$column} } );
$sql .= q{`} . $column . q{` } . $control->getDatabaseFieldType . q{, };
}
$sql .= q{ PRIMARY KEY ( assetId, revisionDate ) ) };
$session->db->write($sql);
# Write to the configuration
$session->config->addToHash( "assets", $installDef->{className}, { category => "basic" } );
return;
} ## end sub install
#----------------------------------------------------------------------------
=head2 isInstalled ( session )
Returns true if the asset is installed. By default, only checks for the
last database table.
=cut
sub isInstalled {
my $class = shift;
my $session = shift;
my $tableName = $class->definition($session)->[0]->{tableName};
my $exists = $session->db->quickScalar( "SHOW TABLES LIKE ?", [$tableName], );
return $exists ? 1 : 0;
}
#----------------------------------------------------------------------------
=head2 uninstall ( session )
Unnstall the asset. C<session> is a WebGUI::Session object from the site to
uninstall the asset from.
=cut
sub uninstall {
my $class = shift;
my $session = shift;
### Uninstall the first member of the definition
my $definition = $class->definition($session);
my $installDef = shift @{$definition};
### Remove all assets contained in the table
my $sth = $session->db->read("SELECT assetId FROM `$installDef->{tableName}`");
while ( my ($assetId) = $sth->array ) {
my $asset = WebGUI::Asset->newById( $session, $assetId );
$asset->purge;
}
# Drop the table
my $sql = q{DROP TABLE `} . $installDef->{tableName} . q{`};
$session->db->write($sql);
$session->config->deleteFromHash( "assets", $installDef->{className} );
return;
} ## end sub uninstall
#----------------------------------------------------------------------------
=head2 upgrade ( session )
Upgrade an existing installation of this asset. Try to reconcile the current
table with the current definition and modify the table if necessary.
=cut
sub upgrade {
my ( $class, $session ) = @_;
unless ( defined $session && $session->isa('WebGUI::Session') ) {
WebGUI::Error::InvalidObject->throw(
expected => 'WebGUI::Session',
got => ( ref $session ),
error => 'Need a session.'
);
}
my $db = $session->db;
my $dbh = $db->dbh;
my $definition = $class->definition($session);
my $properties = $definition->[0]->{properties};
my $tableName = $dbh->quote_identifier( $definition->[0]->{tableName} );
# find out what fields already exist
my %tableFields = ();
my $sth = $db->read( "DESCRIBE " . $tableName );
while ( my ( $col, $type, $null, $key, $default ) = $sth->array ) {
next if ( grep { $_ eq $col } 'assetId', 'revisionDate' );
$tableFields{$col} = { type => $type, };
}
# update existing and create new fields
foreach my $property ( keys %{$properties} ) {
my $control = WebGUI::Form::DynamicField->new( $session, %{ $properties->{$property} }, );
my $fieldType = $control->getDatabaseFieldType;
if ( exists $tableFields{$property} ) {
my $changed = 0;
# parse database table field type
$tableFields{$property}{type} =~ m/^(\w+)(\([\d\s,]+\))?$/;
my ( $tableFieldType, $tableFieldLength ) = ( $1, $2 );
# parse form field type
$fieldType =~ m/^(\w+)(\([\d\s,]+\))?\s*(binary)?$/;
my ( $formFieldType, $formFieldLength ) = ( $1, $2 );
# compare table parts to definition
$changed = 1 if ( $tableFieldType ne $formFieldType );
$changed = 1 if ( $tableFieldLength ne $formFieldLength );
# modify if necessary
if ($changed) {
$db->write( "alter table $tableName change column "
. $dbh->quote_identifier($property) . " "
. $dbh->quote_identifier($property)
. " $fieldType " );
}
} ## end if ( exists $tableFields...
else {
$db->write( "alter table $tableName add column " . $dbh->quote_identifier($property) . " $fieldType " );
}
delete $tableFields{$property};
} ## end foreach my $property ( keys...
# delete fields that are no longer in the definition
foreach my $property ( keys %tableFields ) {
if ( $tableFields{$property}{key} ) {
$db->write( "alter table $tableName drop index " . $dbh->quote_identifier($property) );
}
$db->write( "alter table $tableName drop column " . $dbh->quote_identifier($property) );
}
return 1;
} ## end sub upgrade
# TODO: Add updateTemplates and getTemplatePackage
# or some other manner of installing and maintaining default template package
1;