Skip to content

Commit

Permalink
Update lastPost information in the Thread and CS when a Post is archi…
Browse files Browse the repository at this point in the history
…ved. Made a separate method so it can be used by other actions, and in the upgrade script. Fixes bug #11628.
  • Loading branch information
perlDreamer committed Jun 21, 2010
1 parent 73d6ed7 commit 54c5601
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 7 deletions.
1 change: 1 addition & 0 deletions docs/changelog/7.x.x.txt
Expand Up @@ -3,6 +3,7 @@
- fixed #11656: Thingy: Select list fields are not sorted properly
- fixed #11662: yahooapis.com sourced links
- fixed #11658: tmpl var message missing in template help for the cart
- fixed #11628: Message Board: Last Post doesn't show up in CS Thread List

7.9.7
- added #11571: Allow return from photo edit view to gallery edit view
Expand Down
42 changes: 40 additions & 2 deletions docs/upgrades/upgrade_7.9.7-7.9.8.pl
Expand Up @@ -22,17 +22,19 @@ BEGIN
use WebGUI::Session;
use WebGUI::Storage;
use WebGUI::Asset;
use WebGUI::Asset::Wobject::Collaboration;
use WebGUI::Asset::Post::Thread;
use WebGUI::ProfileField;


my $toVersion = '7.9.8';
my $quiet; # this line required


my $session = start(); # this line required

# upgrade functions go here
changeFirstDayOfWeekDefault($session);
updateLastPostCS($session);
updateLastPostThread($session);

finish($session); # this line required

Expand All @@ -51,11 +53,47 @@ BEGIN
sub changeFirstDayOfWeekDefault {
my $session = shift;
print "\tMake the default for firstDayOfWeek a number instead of a string... " unless $quiet;
# and here's our code
my $profileField = WebGUI::ProfileField->new($session, 'firstDayOfWeek');
my $properties = $profileField->get();
$properties->{dataDefault} = 0;
$profileField->set($properties);
print "DONE!\n" unless $quiet;
}

#----------------------------------------------------------------------------
# Describe what our function does
sub updateLastPostCS {
my $session = shift;
print "\tUpdating last post information in every Collaboration System. This could take a very long time... " unless $quiet;
# and here's our code
my $getCs = WebGUI::Asset::Wobject::Collaboration->getIsa($session);
CS: while (my $cs = eval { $getCs->() } ) {
next CS if Exception::Class->caught();
last CS if ! $cs;
next CS unless $cs->get('lastPostId');
my $lastPost = WebGUI::Asset->newByDynamicClass($session, $cs->get('lastPostId'));
next CS unless $lastPost && $lastPost->get('status') eq 'archived';
$lastPost->disqualifyAsLastPost;
}
print "DONE!\n" unless $quiet;
}

#----------------------------------------------------------------------------
# Describe what our function does
sub updateLastPostThread {
my $session = shift;
print "\tUpdating last post information in every Thread. This could also take a very long time... " unless $quiet;
# and here's our code
my $getThread = WebGUI::Asset::Wobject::Collaboration->getIsa($session);
THREAD: while (my $thread = eval { $getThread->() } ) {
next THREAD if Exception::Class->caught();
last THREAD if ! $thread;
next THREAD unless $thread->get('lastPostId');
my $lastPost = WebGUI::Asset->newByDynamicClass($session, $thread->get('lastPostId'));
next THREAD unless $lastPost && $lastPost->get('status') eq 'archived';
$lastPost->disqualifyAsLastPost;
}
print "DONE!\n" unless $quiet;
}

Expand Down
87 changes: 82 additions & 5 deletions lib/WebGUI/Asset/Post.pm
Expand Up @@ -62,6 +62,7 @@ sub _fixReplyCount {
my $lastPostId = $asset->getLineage( [ qw{ self descendants } ], {
isa => 'WebGUI::Asset::Post',
orderByClause => 'assetData.revisionDate desc',
limit => 1,
} )->[0];

if (my $lastPost = WebGUI::Asset->newByDynamicClass( $self->session, $lastPostId ) ) {
Expand Down Expand Up @@ -353,6 +354,53 @@ sub definition {
}


#-------------------------------------------------------------------

=head2 disqualifyAsLastPost ( )
This method should be called whenever something happens to the Post or Thread that would disqualify
it as being the last post in a Thread, or Collaboration System. Good examples are cutting to the
clipboard, trashing, or archiving.
If the Post was the last post, it will find the second to last post for each kind of parent asset,
and update that asset with that Post's information.
=cut

sub disqualifyAsLastPost {
my $self = shift;
my $thread = $self->getThread;
if ($thread->get('lastPostId') eq $self->getId) {
my $secondary_post = $thread->getLineage(['descendants'], {
returnObjects => 1,
includeOnlyClasses => ["WebGUI::Asset::Post", ],
limit => 1,
orderByClause => 'revisionDate,lineage DESC',
})->[0];
if ($secondary_post) { ##Handle edge case for no other
$thread->update({ lastPostId => $secondary_post->getId, lastPostDate => $secondary_post->get('creationDate'), });
}
else {
$thread->update({ lastPostId => '', lastPostDate => '', });
}
}
my $cs = $thread->getParent;
if ($cs->get('lastPostId') eq $self->getId) {
my $secondary_post = $cs->getLineage(['descendants'], {
returnObjects => 1,
includeOnlyClasses => ["WebGUI::Asset::Post","WebGUI::Asset::Post::Thread"],
limit => 1,
orderByClause => 'revisionDate DESC',
})->[0];
if ($secondary_post) { ##Handle edge case for no other
$cs->update({ lastPostId => $secondary_post->getId, lastPostDate => $secondary_post->get('creationDate'), });
}
else {
$cs->update({ lastPostId => '', lastPostDate => '', });
}
}
}

#-------------------------------------------------------------------

=head2 DESTROY
Expand Down Expand Up @@ -1188,6 +1236,31 @@ sub purgeRevision {



#-------------------------------------------------------------------

=head2 qualifyAsLastPost ( )
This method should be called whenever something happens to the Post or Thread that would qualify
it as being the last post in a Thread, or Collaboration System. Good examples are pasting from
the clipboard, restoring from the trash, or changing the state from archiving.
It checks the parent Thread and CS to see if it is now the last Post, and updates that asset with
its information.
=cut

sub qualifyAsLastPost {
my ($self) = @_;
my $thread = $self->getThread();
if ($self->get('creationDate') > $thread->get('lastPostDate')) {
$thread->update({ lastPostId => $self->getId, lastPostDate => $self->get('creationDate'), });
}
my $cs = $thread->getParent;
if ($self->get('creationDate') > $cs->get('lastPostDate')) {
$cs->update({ lastPostId => $self->getId, lastPostDate => $self->get('creationDate'), });
}
}

#-------------------------------------------------------------------

=head2 rate ( rating )
Expand Down Expand Up @@ -1292,14 +1365,16 @@ sub setParent {

=head2 setStatusArchived ( )
Sets the status of this post to archived.
Sets the status of this post to archived. Updates the parent thread and CS to remove
the lastPost, if this post is the last post.
=cut


sub setStatusArchived {
my ($self) = @_;
$self->update({status=>'archived'});
my ($self) = @_;
$self->update({status=>'archived'});
$self->disqualifyAsLastPost;
}


Expand All @@ -1308,13 +1383,15 @@ sub setStatusArchived {
=head2 setStatusUnarchived ( )
Sets the status of this post to approved, but does so without any of the normal notifications and other stuff.
Updates the last post information in the parent Thread and CS if applicable.
=cut


sub setStatusUnarchived {
my ($self) = @_;
$self->update({status=>'approved'}) if ($self->get("status") eq "archived");
my ($self) = @_;
$self->update({status=>'approved'}) if ($self->get("status") eq "archived");
$self->qualifyAsLastPost;
}

#-------------------------------------------------------------------
Expand Down
122 changes: 122 additions & 0 deletions t/Asset/Post/archiving.t
@@ -0,0 +1,122 @@
#-------------------------------------------------------------------
# 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
#-------------------------------------------------------------------

# 1. The basic framework for a test suite for the Post Asset.
# Includes setup, cleanup, boilerplate, etc. Basically the really boring,
# repetitive parts of the test that you don't want to write yourself.
# 2. The tests for the features I've implemented; namely, functionality and
# general access controls on who can edit a post.

use FindBin;
use strict;
use lib "$FindBin::Bin/../../lib";
use WebGUI::Test;
use WebGUI::Session;
use Test::More tests => 13; # increment this value for each test you create
use WebGUI::Asset::Wobject::Collaboration;
use WebGUI::Asset::Post;
use WebGUI::Asset::Post::Thread;

my $session = WebGUI::Test->session;

# Do our work in the import node
my $node = WebGUI::Asset->getImportNode($session);

# Grab a named version tag
my $versionTag = WebGUI::VersionTag->getWorking($session);
$versionTag->set({name=>"Collab setup"});

# Need to create a Collaboration system in which the post lives.
my @addArgs = ( undef, undef, { skipAutoCommitWorkflows => 1, skipNotification => 1 } );

my $collab = $node->addChild({className => 'WebGUI::Asset::Wobject::Collaboration'}, @addArgs);

# finally, add posts and threads to the collaboration system

my $first_thread = $collab->addChild(
{ className => 'WebGUI::Asset::Post::Thread', },
undef,
WebGUI::Test->webguiBirthday,
{ skipAutoCommitWorkflows => 1, skipNotification => 1 }
);

my $second_thread = $collab->addChild(
{ className => 'WebGUI::Asset::Post::Thread', },
undef,
WebGUI::Test->webguiBirthday,
{ skipAutoCommitWorkflows => 1, skipNotification => 1 }
);

##Thread 1, Post 1 => t1p1
my $t1p1 = $first_thread->addChild(
{ className => 'WebGUI::Asset::Post', },
undef,
WebGUI::Test->webguiBirthday,
{ skipAutoCommitWorkflows => 1, skipNotification => 1 }
);

my $t1p2 = $first_thread->addChild(
{ className => 'WebGUI::Asset::Post', },
undef,
WebGUI::Test->webguiBirthday + 1,
{ skipAutoCommitWorkflows => 1, skipNotification => 1 }
);

my $past = time()-15;

my $t2p1 = $second_thread->addChild(
{ className => 'WebGUI::Asset::Post', },
undef,
$past,
{ skipAutoCommitWorkflows => 1, skipNotification => 1 }
);

my $t2p2 = $second_thread->addChild(
{ className => 'WebGUI::Asset::Post', },
undef,
undef,
{ skipAutoCommitWorkflows => 1, skipNotification => 1 }
);

$versionTag->commit();
WebGUI::Test->addToCleanup($versionTag);

foreach my $asset ($collab, $t1p1, $t1p2, $t2p1, $t2p2, $first_thread, $second_thread, ) {
$asset = $asset->cloneFromDb;
}

is $collab->getChildCount, 2, 'collab has correct number of children';

is $collab->get('lastPostId'), $t2p2->getId, 'lastPostId set in collab';
is $collab->get('lastPostDate'), $t2p2->get('creationDate'), 'lastPostDate, too';

$t2p2->setStatusArchived;
is $t2p2->get('status'), 'archived', 'setStatusArchived set the post to be archived';

$second_thread = $second_thread->cloneFromDb;
is $second_thread->get('lastPostId'), $t2p1->getId, '.. updated lastPostId in the thread';
is $second_thread->get('lastPostDate'), $t2p1->get('creationDate'), '... lastPostDate, too';

$collab = $collab->cloneFromDb;
is $collab->get('lastPostId'), $t2p1->getId, '.. updated lastPostId in the CS';
is $collab->get('lastPostDate'), $t2p1->get('creationDate'), '... lastPostDate, too';

$t2p2->setStatusUnarchived;
is $t2p2->get('status'), 'approved', 'setStatusUnarchived sets the post back to approved';

$second_thread = $second_thread->cloneFromDb;
is $second_thread->get('lastPostId'), $t2p2->getId, '.. updated lastPostId in the thread';
is $second_thread->get('lastPostDate'), $t2p2->get('creationDate'), '... lastPostDate, too';

$collab = $collab->cloneFromDb;
is $collab->get('lastPostId'), $t2p2->getId, '.. updated lastPostId in the CS';
is $collab->get('lastPostDate'), $t2p2->get('creationDate'), '... lastPostDate, too';

#vim:ft=perl

0 comments on commit 54c5601

Please sign in to comment.