diff --git a/docs/changelog/6.x.x.txt b/docs/changelog/6.x.x.txt
index 866d94553..27cf0fd4d 100644
--- a/docs/changelog/6.x.x.txt
+++ b/docs/changelog/6.x.x.txt
@@ -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
diff --git a/docs/upgrades/upgrade_6.8.7-6.99.0.pl b/docs/upgrades/upgrade_6.8.7-6.99.0.pl
index 4ded98533..5f4169445 100644
--- a/docs/upgrades/upgrade_6.8.7-6.99.0.pl
+++ b/docs/upgrades/upgrade_6.8.7-6.99.0.pl
@@ -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");
}
#-------------------------------------------------
diff --git a/lib/WebGUI/AdSpace.pm b/lib/WebGUI/AdSpace.pm
new file mode 100644
index 000000000..5275ee24e
--- /dev/null
+++ b/lib/WebGUI/AdSpace.pm
@@ -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;
+
diff --git a/lib/WebGUI/AdSpace/Ad.pm b/lib/WebGUI/AdSpace/Ad.pm
new file mode 100644
index 000000000..92b3d4f9f
--- /dev/null
+++ b/lib/WebGUI/AdSpace/Ad.pm
@@ -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} = 'getId).'">';
+ } elsif ($self->get("type") eq "image") {
+ my $storage = WebGUI::Storage::Image->new($self->session, $self->get("storageId"));
+ $self->{_properties}{renderedAd} = 'getId).'">';
+
+ } elsif ($self->get("type") eq "rich") {
+ $self->{_properties}{renderedAd} = $self->get("richMedia");
+ }
+ $self->session->db->setRow("advertisement","adId",$self->{_properties});
+}
+
+1;
+
diff --git a/lib/WebGUI/Asset/Post.pm b/lib/WebGUI/Asset/Post.pm
index baa10ec58..f9ac4729d 100644
--- a/lib/WebGUI/Asset/Post.pm
+++ b/lib/WebGUI/Asset/Post.pm
@@ -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;
}
diff --git a/lib/WebGUI/Asset/Post/Thread.pm b/lib/WebGUI/Asset/Post/Thread.pm
index 3bdcef26b..485d185a6 100644
--- a/lib/WebGUI/Asset/Post/Thread.pm
+++ b/lib/WebGUI/Asset/Post/Thread.pm
@@ -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.
diff --git a/lib/WebGUI/Asset/Wobject/Collaboration.pm b/lib/WebGUI/Asset/Wobject/Collaboration.pm
index a9a3fd7fe..06f63b656 100644
--- a/lib/WebGUI/Asset/Wobject/Collaboration.pm
+++ b/lib/WebGUI/Asset/Wobject/Collaboration.pm
@@ -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
diff --git a/lib/WebGUI/Operation.pm b/lib/WebGUI/Operation.pm
index 9e414b824..750dd73af 100644
--- a/lib/WebGUI/Operation.pm
+++ b/lib/WebGUI/Operation.pm
@@ -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',
diff --git a/lib/WebGUI/Operation/AdSpace.pm b/lib/WebGUI/Operation/AdSpace.pm
new file mode 100644
index 000000000..2c2cf0d43
--- /dev/null
+++ b/lib/WebGUI/Operation/AdSpace.pm
@@ -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;
diff --git a/lib/WebGUI/i18n/English/Asset_Collaboration.pm b/lib/WebGUI/i18n/English/Asset_Collaboration.pm
index fe79494ee..66e1c162b 100644
--- a/lib/WebGUI/i18n/English/Asset_Collaboration.pm
+++ b/lib/WebGUI/i18n/English/Asset_Collaboration.pm
@@ -1049,6 +1049,10 @@ A conditional indicating that is true if this Post is the fifth in this Collabor
user.isPoster
A conditional indicating that is true if the current user submitted this Post.
+
+user.hasRead
+A conditional indicating whether a user has read this thread.
+
avatar.url
A URL to the avatar for the owner of the Post, if avatars are enabled and the
diff --git a/lib/WebGUI/i18n/English/Asset_Post.pm b/lib/WebGUI/i18n/English/Asset_Post.pm
index cfa0f89c3..d71c0768f 100644
--- a/lib/WebGUI/i18n/English/Asset_Post.pm
+++ b/lib/WebGUI/i18n/English/Asset_Post.pm
@@ -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.
-isMarkedRead
-A conditional that is true if the post has been marked as read by the user.
-
-
image.url
The URL to the first image attached to the Post.