add ad management system

improved performance of cs threads by about 500%
This commit is contained in:
JT Smith 2006-04-05 03:42:14 +00:00
parent c8956ac0c5
commit d26f1bdd8c
11 changed files with 740 additions and 74 deletions

View file

@ -22,7 +22,9 @@
- Refactored admin bar to be more dynamic.
- Removed start/end dates from assets in favor of the workflow system.
- Readded the purge option to the trash manager.
- Added an advertising management system.
- Added archive/unarchive options to CS threads.
- Increased the performance of CS Thread viewing by 500%.
- Added a database cache option as an alternative to memcached.
- Converted WebGUI to use a new object oriented session system. More details
in migation.txt.
@ -34,7 +36,9 @@
powerful, easier to use, and more flexible.
- Added output chunking as an option for asset www_ methods. The net effect
of this provides a fairly significant performance increase to what would
otherwise be slow or complex pages. More details in migration.txt.
otherwise be slow or complex pages. More details in migration.txt. The
amount of the increase depends upon the complexity of the page, but now
complex pages should render almost as fast as simple pages.
- The SMTP mail backend has been replaced with a new API that's capable of
sending attachments, HTML messages, and more. This will introduce many new
options for developers.
@ -46,9 +50,6 @@
to the database link properties. (Martin Kamerbeek / Procolix)
- Converted config file format from PlainConfig to JSON. The new format is
more powerful and will use slightly less memory.
- fix [ 1406210 ] 6.9 i18n in create.sql, previous.sql broken.
- fix [ 1410577 ] WebGUI::Session not included
- fix [ 1445387 ] 6.9 DataForm add Checkbox List, SellectList broken
- Strengthened security of Captcha validation.
- Added Captcha form control type.
- All IPs used by WebGUI (Settings: debugIp and Group: ipFilter) now accept
@ -63,8 +64,6 @@
- The Navigation Asset now allows setting the MIME type of its output so that
you can generate non-HTML navigations or take advantate of the Google
SiteMap feature.
- [ 1433525 ] 6.9: Compilation errors
- base36 removed from Utility.t because it no longer exists in WebGUI::Utility.pm
- Add tests that verify the integrity of the WebGUI Database.
- Added a karma ranking system to CS threads for conducting popularity
contests.
@ -72,12 +71,7 @@
tabbed view to make scanning for content easier.
- Help for forms now shows the fields that you should see with your UI level.
There is a link to show all fields.
- fix [ 1445393 ] 6.9 WhatNext missing from DataForm editField
- fix [ 1443378 ] 6.99 Commerce system needs to be sessionized
- fix [ 1442942 ] 6.99: listLDAPLinks broken
- fix [ 1430276 ] 6.9: Can't kill active sessions
- fix [ 1429389 ] 6.9: "1" appended to HTML
- fix [ 1433508 ] 6.9: isInGroup does not work correctly
- fix [ 1410577 ] WebGUI::Session not included
- fix a bug where a link was provided to become or delete non-existant users.
- fix bugs with the in-memory session caching of user and group memberships

View file

@ -26,7 +26,7 @@ my $session = start(); # this line required
addWorkflow();
convertMessageLogToInbox();
addCsPopularityContest();
updateCs();
templateParsers();
removeFiles();
addSearchEngine();
@ -41,9 +41,52 @@ addIndexes();
addDatabaseCache();
updateHelpTemplate();
fixImportNodePrivileges();
addAdManager();
finish($session); # this line required
#-------------------------------------------------
sub addAdManager {
print "\tAdding advertising management.\n";
$session->db->write("create table adSpace (
adSpaceId varchar(22) binary not null primary key,
name varchar(35) not null unique key,
title varchar(255) not null,
description text,
costPerImpression decimal(11,2) not null default 0,
minimumImpressions int not null default 1000,
costPerClick decimal(11,2) not null default 0,
minimumClicks int not null default 1000,
width int not null default 468,
height int not null default 60,
groupToPurchase varchar(22) binary not null default '3'
)");
$session->db->write("create table advertisement (
adId varchar(22) binary not null primary key,
adSpaceId varchar(22) binary not null,
ownerUserId varchar(22) binary not null,
isActive int not null default 0,
title varchar(255) not null,
type varchar(15) not null default 'text',
storageId varchar(22) binary,
filename varchar(255),
adText varchar(255),
url text,
richMedia text,
borderColor varchar(7) not null default '#000000',
textColor varchar(7) not null default '#000000',
backgroundColor varchar(7) not null default '#ffffff',
clicks int not null default 0,
clicksBought int not null default 0,
impressions int not null default 0,
impressionsBought int not null default 0,
priority int not null default 0,
nextInPriority bigint not null default 0,
renderedAd text
)");
$session->db->write("alter table advertisement add index adSpaceId_isActive (adSpaceId, isActive)");
}
#-------------------------------------------------
sub fixImportNodePrivileges {
print "\tFixing the privileges of all the content in the import node.\n";
@ -101,12 +144,20 @@ sub convertMessageLogToInbox {
}
#-------------------------------------------------
sub addCsPopularityContest {
print "\tAdding collaboration system popularity system based upon karma.\n";
sub updateCs {
print "\tUpdating the Collaboration System.\n";
print "\t\tAdding collaboration system popularity system based upon karma.\n";
$session->db->write("alter table Collaboration add column defaultKarmaScale integer not null default 1");
$session->db->write("alter table Thread add column karma integer not null default 0");
$session->db->write("alter table Thread add column karmaScale integer not null default 1");
$session->db->write("alter table Thread add column karmaRank decimal(6,6) not null default 0");
print "\t\tIncreasing CS performance.\n";
$session->db->write("alter table Post_rating add index assetId_userId (assetId,userId);");
$session->db->write("alter table Post_rating add index assetId_ipAddress (assetId,ipAddress);");
$session->db->write("delete from Post_read where postId<>threadId");
$session->db->write("alter table Post_read drop column postId");
$session->db->write("alter table Post_read drop column dateRead");
$session->db->write("alter table Post_read rename Thread_read");
}
#-------------------------------------------------

315
lib/WebGUI/AdSpace.pm Normal file
View file

@ -0,0 +1,315 @@
package WebGUI::AdSpace;
=head1 LEGAL
-------------------------------------------------------------------
WebGUI is Copyright 2001-2006 Plain Black Corporation.
-------------------------------------------------------------------
Please read the legal notices (docs/legal.txt) and the license
(docs/license.txt) that came with this distribution before using
this software.
-------------------------------------------------------------------
http://www.plainblack.com info@plainblack.com
-------------------------------------------------------------------
=cut
use strict;
=head1 NAME
Package WebGUI::AdSpace
=head1 DESCRIPTION
This class provides a mechanism for controlling advertisements from within WebGUI.
=head1 SYNOPSIS
use WebGUI::AdSpace;
=head1 METHODS
These methods are available from this class:
=cut
#-------------------------------------------------------------------
=head2 countClick ( adId )
Increments click counter, and returns the URL to send the user to.
=head3 adId
The unique ID of the ad that was clicked.
=cut
sub countClick {
my $self = shift;
my $id = shift;
my ($url) = $self->session->db->quickArray("select url from advertisement where adId=?",[$id]);
$self->session->db->write("update advertisement set clicks=clicks+1 where adId=?",[$id]);
return $url;
}
#-------------------------------------------------------------------
=head2 create ( session, properties )
=head3 session
A reference to the current session
=head3 properties
The properties used to create this object. See the set() method for details.
=cut
sub create {
my $class = shift;
my $session = shift;
my $properties = shift;
return undef unless $properties->{name};
my $test = $class->newByName($session, $properties->{name});
return undef if defined $test;
my $id = $session->db->setRow("adSpace","adSpaceId",{adSpaceId=>"new"});
my $self = $class->new($session, $id);
$self->set($properties);
return $self;
}
#-------------------------------------------------------------------
=head2 delete
Deletes this ad space.
=cut
sub delete {
my $self = shift;
foreach my $ad (@{$self->getAds}) {
$ad->delete;
}
$self->session->db->deleteRow("adSpace","adSpaceId",$self->getId);
$self = undef;
}
#-------------------------------------------------------------------
=head2 DESTROY ( )
Deconstructor.
=cut
sub DESTROY {
my $self = shift;
undef $self;
}
#-------------------------------------------------------------------
=head2 displayImpression ()
Finds out what the next ad is to display, increments it's impression counter, and returns the HTML to display it.
=cut
sub displayImpression {
my $self = shift;
my ($id, $ad, $priority, $clicks, $clicksBought, $impressions, $impressionsBought) = $self->session->db->quickArray("select adId, renderedAd, priority, clicks, clicksBought, impressions, impressionsBought from advertisement where adSpaceId=? and isActive=1 order by nextInPriority asc limit 1",[$self->getId]);
my $isActive = 1;
if ($clicks > $clicksBought && $impressions > $impressionsBought) {
$isActive = 0;
}
$self->session->db->write("update advertisement set impressions=impressions+1, nextInPriority=?, isActive=? where adId=?", [time()+$priority, $id, $isActive]);
return $ad;
}
#-------------------------------------------------------------------
=head2 get ( name )
Returns the value of a property. See set() for a list of properties.
=head3 name
The name of the property to retrieve the value for.
=cut
sub get {
my $self = shift;
my $name = shift;
return $self->{_properties}{$name};
}
#-------------------------------------------------------------------
=head2 getAds ( )
Returns an array reference containing all the ad objects in this ad space.
=cut
sub getAds {
my $self = shift;
my @ads = ();
my $rs = $self->session->db->read("select adId from advertisement where adSpaceId = ?", [$self->getId]);
while (my ($id) = $rs->array) {
push(@ads, WebGUI::AdSpace::Ad->new($self->session, $id));
}
return \@ads;
}
#-------------------------------------------------------------------
=head2 getId
Returns the id of this object.
=cut
sub getId {
my $self = shift;
return $self->{_properties}{adSpaceId};
}
#-------------------------------------------------------------------
=head2 new ( session, id )
Constructor.
=head3 session
A reference to the current session.
=head3 id
The unqiue ID of an ad space location.
=cut
sub new {
my $class = shift;
my $session = shift;
my $id = shift;
my $properties = $session->db->getRow("adSpace","adSpaceId",$id);
return undef unless $properties->{adSpaceId};
bless {_session=>$session, _properties=>$properties}, $class;
}
#-------------------------------------------------------------------
=head2 newByName ( session, name )
Constructor.
=head3 session
A reference to the current session.
=head3 name
The name of the ad space to retrieve.
=cut
sub newByName {
my $class = shift;
my $session = shift;
my $name = shift;
my $properties = $session->db->getRow("adSpace","name",$name);
return undef unless $properties->{adSpaceId};
bless {_session=>$session, _properties=>$properties}, $class;
}
#-------------------------------------------------------------------
=head2 session
Returns a reference to the current session.
=cut
sub session {
my $self = shift;
return $self->{_session};
}
#-------------------------------------------------------------------
=head2 set ( properties )
Updates the properties of an ad space.
=head3 properties
A hash reference containing the properties to set.
=head4 name
The name that will be used to retrieve this ad space when it's in use one the web site. It should not contain spaces or characters other than alpha-numeric.
=head4 title
A human readable title for this ad space.
=head4 description
A human readable description for this ad space.
=head4 costPerImpression
A float that represents how much it will cost an advertiser every time an ad is viewed in this ad space.
=head4 minimumImpressions
An integer indicating the minimum number of impressions an advertiser is allowed to purchase.
=head4 costPerClick
A float that represents how much it will cost an advertiser everytime someone clicks on an ad in this ad space.
=head4 minimumClicks
An integer indicating the minimum number of clicks an advertiser is allowed to purchase.
=head4 groupToPurchase
A groupId representing the group allowed to purchase ads directly from the web site.
=head4 width
The width, in pixels, of this ad space.
=head4 height
The height, in pixels, of this ad space.
=cut
sub set {
my $self = shift;
my $properties = shift;
$self->{_properties}{name} = $properties->{name} || $self->{_properties}{name} || "Unnamed";
$self->{_properties}{title} = $properties->{title} || $self->{_properties}{title} || "Untitled";
$self->{_properties}{description} = $properties->{description} || $self->{_properties}{description};
$self->{_properties}{costPerImpression} = exists $properties->{costPerImpression} ? $properties->{costPerImpression} : $self->{_properties}{costPerImpression};
$self->{_properties}{costPerClick} = exists $properties->{costPerClick} ? $properties->{costPerClick} : $self->{_properties}{costPerClick};
$self->{_properties}{minimumImpressions} = $properties->{minimumImpressions} || $self->{_properties}{minimumImpressions};
$self->{_properties}{minimumClicks} = $properties->{minimumClicks} || $self->{_properties}{minimumClicks};
$self->{_properties}{groupToPurchase} = $properties->{groupToPurchase} || $self->{_properties}{groupToPurchase} || "3";
$self->{_properties}{width} = $properties->{width} || $self->{_properties}{width} || "468";
$self->{_properties}{height} = $properties->{height} || $self->{_properties}{height} || "60";
$self->session->db->setRow("adSpace","adSpaceId",$self->{_properties});
}
1;

270
lib/WebGUI/AdSpace/Ad.pm Normal file
View file

@ -0,0 +1,270 @@
package WebGUI::AdSpace::Ad;
=head1 LEGAL
-------------------------------------------------------------------
WebGUI is Copyright 2001-2006 Plain Black Corporation.
-------------------------------------------------------------------
Please read the legal notices (docs/legal.txt) and the license
(docs/license.txt) that came with this distribution before using
this software.
-------------------------------------------------------------------
http://www.plainblack.com info@plainblack.com
-------------------------------------------------------------------
=cut
use strict;
use WebGUI::AdSpace;
use WebGUI::Storage::Image;
=head1 NAME
Package WebGUI::AdSpace::Ad
=head1 DESCRIPTION
This class provides an mechanism for manipulating an individual ad within an ad space.
=head1 SYNOPSIS
use WebGUI::AdSpace::Ad;
=head1 METHODS
These methods are available from this class:
=cut
#-------------------------------------------------------------------
=head2 create ( session, adSpaceId, properties )
=head3 session
A reference to the current session
=head3 adSpaceId
The unique id of an ad space to attach this ad to.
=head3 properties
The properties used to create this object. See the set() method for details.
=cut
sub create {
my $class = shift;
my $session = shift;
my $properties = shift;
my $id = $session->db->setRow("adSpace","adSpaceId",{adSpaceId=>"new"});
my $self = $class->new($session, $id);
$self->set($properties);
return $self;
}
#-------------------------------------------------------------------
=head2 delete
Deletes this ad.
=cut
sub delete {
my $self = shift;
my $storage = WebGUI::Storage::Image->new($self->session, $self->get("storageId"));
$storage->delete;
$self->session->db->deleteRow("advertisement","adId",$self->getId);
$self = undef;
}
#-------------------------------------------------------------------
=head2 DESTROY ( )
Deconstructor.
=cut
sub DESTROY {
my $self = shift;
undef $self;
}
#-------------------------------------------------------------------
=head2 get ( name )
Returns the value of a property.
=head3 name
The name of the property to retrieve the value for.
=cut
sub get {
my $self = shift;
my $name = shift;
return $self->{_properties}{$name};
}
#-------------------------------------------------------------------
=head2 getId
Returns the id of this object.
=cut
sub getId {
my $self = shift;
return $self->{_properties}{adId};
}
#-------------------------------------------------------------------
=head2 new ( session, id )
Constructor.
=head3 session
A reference to the current session.
=head3 id
The unqiue ID of an ad.
=cut
sub new {
my $class = shift;
my $session = shift;
my $id = shift;
my $properties = $session->db->getRow("advertisement","adId",$id);
return undef unless $properties->{adId};
bless {_session=>$session, _properties=>$properties}, $class;
}
#-------------------------------------------------------------------
=head2 session
Returns a reference to the current session.
=cut
sub session {
my $self = shift;
return $self->{_session};
}
#-------------------------------------------------------------------
=head2 set ( properties )
Updates the properties of an ad space.
=head3 properties
A hash reference containing the properties to set.
=head4 title
A human readable name for this ad, which will be displayed in the ad, and in menus.
=head4 adText
A chunk of text, no longer than 255 characters that will be displayed in text ads.
=head4 storageId
The id of the storage location that holds the image for an image style ad.
=head4 filename
The name of the file from the storage location to display for an image ad.
=head4 richMedia
A chunk of HTML that will be inserted into the page for rich media ads.
=head4 ownerUserId
The user that owns this ad, and will be able to view reports for it, etc.
=head4 isActive
A boolean indicating whether the ad is active or not.
=head4 type
The type of ad this is. Defaults to 'text'. Choose from 'text', 'image', or 'rich'.
=head4 borderColor
The hex color to be used to display the border on a text based ad.
=head4 textColor
THe hex color to be used to display the text on a test based ad.
=head4 backgroundColor
The hex color to be used to display the background on a text based ad.
=head4 priority
An integer that will be used to scale the frequency of ad placement based upon traffic to your site. The lower the number, the more frequently it will be displayed. For example, on a site with an average of 1 impression per second, if you have two ads, one with a priority of 0 and another with a priority of 100, the first ad will be displayed 100 times more frequently than the second ad.
=head4 url
The URL that the user will be directed to when clicking on the ad. This is used in text and image based ads.
=head4 clicksBought
The number of clicks that have been purchased for this ad.
=head4 impressionsBought
=cut
sub set {
my $self = shift;
my $properties = shift;
$self->{_properties}{title} = $properties->{title} || $self->{_properties}{title} || "Untitled";
$self->{_properties}{clicksBought} = $properties->{clicksBought} || $self->{_properties}{clicksBought};
$self->{_properties}{impressionsBought} = $properties->{impressionsBought} || $self->{_properties}{impressionsBought};
$self->{_properties}{url} = $properties->{url} || $self->{_properties}{url};
$self->{_properties}{adText} = $properties->{adText} || $self->{_properties}{adText};
$self->{_properties}{filename} = $properties->{filename} || $self->{_properties}{filename};
$self->{_properties}{storageId} = $properties->{storageId} || $self->{_properties}{storageId};
$self->{_properties}{richMedia} = $properties->{richMedia} || $self->{_properties}{richMedia};
$self->{_properties}{ownerUserId} = $properties->{ownerUserId} || $self->{_properties}{ownerUserId} || "3";
$self->{_properties}{isActive} = exists $properties->{isActive} ? $properties->{isActive} : $self->{_properties}{isActive};
$self->{_properties}{type} = $properties->{type} || $self->{_properties}{type} || "text";
$self->{_properties}{borderColor} = $properties->{borderColor} || $self->{_properties}{borderColor} || "#000000";
$self->{_properties}{textColor} = $properties->{textColor} || $self->{_properties}{textColor} || "#000000";
$self->{_properties}{backgroundColor} = $properties->{backgroundColor} || $self->{_properties}{backgroundColor} || "#ffffff";
$self->{_properties}{priority} = $properties->{priority} || $self->{_properties}{priority} || "0";
# prerender the ad for faster display
my $adSpace = WebGUI::AdSpace->new($self->session, $self->get("adSpaceId"));
if ($self->get("type") eq "text") {
$self->{_properties}{renderedAd} = '<a href="'.$self->session->url->gateway(undef, "op=clickAd;id=".$self->getId).'"><div style="overflow: hidden; width: '.$adSpace->get("width").'px; height: '.$adSpace->get("height").'px; color: '.$self->get("textColor").'; background-color: '.$self->get("backgroundColor").'; border: 1px solid '.$self->get("borderColor").';"><b>'.$self->get("title").'</b><br />'.$self->get("adText").'</div></a>';
} elsif ($self->get("type") eq "image") {
my $storage = WebGUI::Storage::Image->new($self->session, $self->get("storageId"));
$self->{_properties}{renderedAd} = '<a href="'.$self->session->url->gateway(undef, "op=clickAd;id=".$self->getId).'"><div style="overflow: hidden; width: '.$adSpace->get("width").'px; height: '.$adSpace->get("height").'px;"><img src="'.$storage->getUrl($self->get("filename")).'" style="border: 0px;" alt="'.$self->get("title").'" /></div></a>';
} elsif ($self->get("type") eq "rich") {
$self->{_properties}{renderedAd} = $self->get("richMedia");
}
$self->session->db->setRow("advertisement","adId",$self->{_properties});
}
1;

View file

@ -46,7 +46,8 @@ sub addRevision {
if ($self->get("storageId")) {
my $newStorage = WebGUI::Storage->get($self->session,$self->get("storageId"))->copy;
$newSelf->update({storageId=>$newStorage->getId});
}
}
$self->getThread->unmarkRead;
return $newSelf;
}
@ -412,7 +413,6 @@ sub getTemplateVars {
$var{'rate.url.4'} = $self->getRateUrl(4);
$var{'rate.url.5'} = $self->getRateUrl(5);
$var{'hasRated'} = $self->hasRated;
$var{'isMarkedRead'} = $self->isMarkedRead;
my $gotImage;
my $gotAttachment;
@{$var{'attachment_loop'}} = ();
@ -502,9 +502,12 @@ Returns a boolean indicating whether this user has already rated this post.
sub hasRated {
my $self = shift;
return 1 if $self->isPoster;
my ($flag) = $self->session->db->quickArray("select count(*) from Post_rating where assetId="
.$self->session->db->quote($self->getId)." and ((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("REMOTE_ADDR"))."))");
my $flag = 0;
if ($self->session->user->userId eq "1") {
($flag) = $self->session->db->quickArray("select count(*) from Post_rating where assetId=? and ipAddress=?",[$self->getId, $self->session->env->get("REMOTE_ADDR")]);
} else {
($flag) = $self->session->db->quickArray("select count(*) from Post_rating where assetId=? and userId=?",[$self->getId, $self->session->user->userId]);
}
return $flag;
}
@ -547,21 +550,6 @@ sub incrementViews {
#-------------------------------------------------------------------
=head2 isMarkedRead ( )
Returns a boolean indicating whether this post is marked read for the user.
=cut
sub isMarkedRead {
my $self = shift;
return 1 if $self->isPoster;
my ($isRead) = $self->session->db->quickArray("select count(*) from Post_read where userId=".$self->session->db->quote($self->session->user->userId)." and postId=".$self->session->db->quote($self->getId));
return $isRead;
}
#-------------------------------------------------------------------
=head2 isPoster ( )
Returns a boolean that is true if the current user created this post and is not a visitor.
@ -588,22 +576,6 @@ sub isReply {
}
#-------------------------------------------------------------------
=head2 markRead ( )
Marks this post read for this user.
=cut
sub markRead {
my $self = shift;
unless ($self->isMarkedRead) {
$self->session->db->write("insert into Post_read (userId, postId, threadId, readDate) values (".$self->session->db->quote($self->session->user->userId).",
".$self->session->db->quote($self->getId).", ".$self->session->db->quote($self->get("threadId")).", ".$self->session->datetime->time().")");
}
}
#-------------------------------------------------------------------
=head2 notifySubscribers ( )
@ -719,8 +691,6 @@ sub purge {
$storage->delete if defined $storage;
}
$sth->finish;
$self->session->db->write("delete from Post_rating where assetId=".$self->session->db->quote($self->getId));
$self->session->db->write("delete from Post_read where postId=".$self->session->db->quote($self->getId));
return $self->SUPER::purge;
}
@ -838,19 +808,6 @@ sub trash {
#-------------------------------------------------------------------
=head2 unmarkRead ( )
Negates the markRead method.
=cut
sub unmarkRead {
my $self = shift;
$self->session->db->write("delete from forumRead where userId=".$self->session->db->quote($self->session->user->userId)." and postId=".$self->session->db->quote($self->getId));
}
#-------------------------------------------------------------------
=head2 update
We overload the update method from WebGUI::Asset in order to handle file system privileges.
@ -873,7 +830,6 @@ sub update {
#-------------------------------------------------------------------
sub view {
my $self = shift;
$self->markRead;
$self->incrementViews;
return $self->getThread->view;
}
@ -1120,7 +1076,6 @@ sub www_showConfirmation {
#-------------------------------------------------------------------
sub www_view {
my $self = shift;
$self->markRead;
$self->incrementViews;
return $self->getThread->www_view;
}

View file

@ -434,7 +434,7 @@ Returns a boolean indicating whether this thread is marked read for the user.
sub isMarkedRead {
my $self = shift;
return 1 if $self->isPoster;
my ($isRead) = $self->session->db->quickArray("select count(*) from Post_read where userId=".$self->session->db->quote($self->session->user->userId)." and threadId=".$self->session->db->quote($self->getId)." and postId=".$self->session->db->quote($self->get("lastPostId")));
my ($isRead) = $self->session->db->quickArray("select count(*) from Thread_read where threadId=? and userId=?",[$self->getId,$self->session->user->userId]);
return $isRead;
}
@ -479,6 +479,19 @@ sub lock {
}
#-------------------------------------------------------------------
=head2 markRead ( )
Marks this post read for this user.
=cut
sub markRead {
my $self = shift;
$self->session->db->write("replace into Thread_read (threadId, userId) values (?,?)",[$self->getId,$self->session->user->userId]);
}
#-------------------------------------------------------------------
=head2 prepareView ( )
@ -512,6 +525,12 @@ sub processPropertiesFromFormPost {
}
}
#-------------------------------------------------------------------
sub purge {
my $self = shift;
$self->session->db->write("delete from Thread_read where postId=?",[$self->getId]);
return $self->SUPER::purge;
}
#-------------------------------------------------------------------
@ -673,6 +692,19 @@ sub unlock {
#-------------------------------------------------------------------
=head2 unmarkRead ( )
unmarks this post read for all users.
=cut
sub unmarkRead {
my $self = shift;
$self->session->db->write("delete from Thread_read where threadId=?",[$self->getId]);
}
#-------------------------------------------------------------------
=head2 unstick ( )
Negates the stick method.

View file

@ -47,9 +47,10 @@ sub appendPostListTemplateVars {
push(@rating_loop,{'rating_loop.count'=>$i});
}
my %lastReply;
my $hasRead = 0;
if ($post->get("className") =~ /Thread/) {
my $lastPost = $post->getLastPost();
if ($self->get("displayLastReply")) {
my $lastPost = $post->getLastPost();
%lastReply = (
"lastReply.url"=>$lastPost->getUrl.'#'.$lastPost->getId,
"lastReply.title"=>$lastPost->get("title"),
@ -60,6 +61,7 @@ sub appendPostListTemplateVars {
"lastReply.timeSubmitted.human"=>$self->session->datetime->epochToHuman($lastPost->get("dateSubmitted"),"%Z")
);
}
$hasRead = $post->isMarkedRead;
}
my $url;
if ($post->get("status") eq "pending") {
@ -88,6 +90,7 @@ sub appendPostListTemplateVars {
"isThird"=>(($i+1)%3==0),
"isFourth"=>(($i+1)%4==0),
"isFifth"=>(($i+1)%5==0),
"user.hasRead" => $hasRead,
"user.isPoster"=>$post->isPoster,
"avatar.url"=>$post->getAvatarUrl,
%lastReply

View file

@ -77,6 +77,7 @@ Returns a hash reference containing operation and package names.
sub getOperations {
return {
'clickAd' => 'WebGUI::Operation::AdSpace',
'editVersionTag' => 'WebGUI::Operation::VersionTag',
'editVersionTagSave' => 'WebGUI::Operation::VersionTag',
'commitVersionTag' => 'WebGUI::Operation::VersionTag',

View file

@ -0,0 +1,45 @@
package WebGUI::Operation::AdSpace.pm
#-------------------------------------------------------------------
# WebGUI is Copyright 2001-2006 Plain Black Corporation.
#-------------------------------------------------------------------
# Please read the legal notices (docs/legal.txt) and the license
# (docs/license.txt) that came with this distribution before using
# this software.
#-------------------------------------------------------------------
# http://www.plainblack.com info@plainblack.com
#-------------------------------------------------------------------
use strict;
use WebGUI::AdSpace;
=head1 NAME
Package WebGUI::Operation::AdSpace
=head1 DESCRIPTION
Operation handler for advertising functions.
=cut
#-------------------------------------------------------------------
=head2 www_clickAd ( )
Handles a click on an advertisement.
=cut
sub www_clickAd {
my $session = shift;
my $id = $session->form->param("adId");
return undef unless $id;
my $url = WebGUI::AdSpace->countClick($session, $id);
$session->http->setRedirect($url);
return "Redirecting to $url";
}
1;

View file

@ -1049,6 +1049,10 @@ A conditional indicating that is true if this Post is the fifth in this Collabor
<b>user.isPoster</b><br>
A conditional indicating that is true if the current user submitted this Post.
<p>
<b>user.hasRead</b><br>
A conditional indicating whether a user has read this thread.
<p>
<b>avatar.url</b><br>
A URL to the avatar for the owner of the Post, if avatars are enabled and the

View file

@ -224,10 +224,6 @@ URLs that are used to rate this post. N goes from 1 to 5.
A conditional that is true if the user has already rated this Post.
<p>
<b>isMarkedRead</b><br>
A conditional that is true if the post has been marked as read by the user.
<p>
<b>image.url</b><br>
The URL to the first image attached to the Post.
<p>