# This code is a part of Slash, and is released under the GPL. # Copyright 1997-2001 by Open Source Development Network. See README # and COPYING for more information, or see http://slashcode.com/. # $Id: Journal.pm,v 1.2.2.27 2002/01/02 18:58:46 pudge Exp $ package Slash::Journal; use strict; use DBIx::Password; use Slash; use Slash::Utility; use Slash::DB::Utility; use vars qw($VERSION @EXPORT); use base 'Exporter'; use base 'Slash::DB::Utility'; use base 'Slash::DB::MySQL'; ($VERSION) = ' $Revision: 1.2.2.27 $ ' =~ /\$Revision:\s+([^\s]+)/; @EXPORT = qw( MSG_CODE_JOURNAL_FRIEND ); use constant MSG_CODE_JOURNAL_FRIEND => 5; # On a side note, I am not sure if I liked the way I named the methods either. # -Brian sub new { my($class, $user) = @_; my $self = {}; my $slashdb = getCurrentDB(); my $plugins = $slashdb->getDescriptions('plugins'); return unless $plugins->{'Journal'}; bless($self, $class); $self->{virtual_user} = $user; $self->sqlConnect; return $self; } sub set { my($self, $id, $values) = @_; my $uid = $ENV{SLASH_USER}; return unless $self->sqlSelect('id', 'journals', "uid=$uid AND id=$id"); my(%j1, %j2); %j1 = %$values; $j2{article} = delete $j1{article}; $self->sqlUpdate('journals', \%j1, "id=$id") if keys %j1; $self->sqlUpdate('journals_text', \%j2, "id=$id") if $j2{article}; } sub getsByUid { my($self, $uid, $start, $limit, $id) = @_; my $order = "ORDER BY date DESC"; $order .= " LIMIT $start, $limit" if $limit; my $where = "uid = $uid AND journals.id = journals_text.id"; $where .= " AND journals.id = $id" if $id; my $answer = $self->sqlSelectAll( 'date, article, description, journals.id, posttype, tid, discussion', 'journals, journals_text', $where, $order ); return $answer; } sub list { my($self, $uid, $limit) = @_; $uid ||= 0; # no SQL syntax error my $order = "ORDER BY date DESC"; $order .= " LIMIT $limit" if $limit; my $answer = $self->sqlSelectAll('id, date, description', 'journals', "uid = $uid", $order); return $answer; } sub create { my($self, $description, $article, $posttype, $tid) = @_; return unless $description; return unless $article; return unless $tid; my $uid = $ENV{SLASH_USER}; $self->sqlInsert("journals", { uid => $uid, description => $description, tid => $tid, -date => 'now()', posttype => $posttype, }); my($id) = $self->getLastInsertId('journals', 'id'); return unless $id; $self->sqlInsert("journals_text", { id => $id, article => $article, }); my($date) = $self->sqlSelect('date', 'journals', "id=$id"); my $slashdb = getCurrentDB(); $slashdb->setUser($uid, { journal_last_entry_date => $date }); return $id; } sub remove { my($self, $id) = @_; my $uid = $ENV{SLASH_USER}; if ($self->sqlDo("DELETE FROM journals WHERE uid=$uid AND id=$id") == 0) { # Return value 0E0 means "no rows deleted" (i.e. this user owns # no such journal) and undef means "error." Either way, abort. return; } $self->sqlDo("DELETE FROM journals_text WHERE id=$id"); my $date = $self->sqlSelect('MAX(date)', 'journals', "uid=$uid"); if ($date) { $date = $self->sqlQuote($date); } else { $date = "NULL"; } my $slashdb = getCurrentDB(); $slashdb->setUser($uid, { -journal_last_entry_date => $date }); } sub friends { my($self) = @_; my $uid = $ENV{SLASH_USER}; # old style that ALMOST worked ... # my $friends = $self->sqlSelectAll( # 'u.nickname, j.friend, MAX(jo.date) as date, jo.description', # 'journals as jo, journal_friends as j,users as u', # "j.uid = $uid AND j.friend = u.uid AND j.friend = jo.uid", # 'GROUP BY u.nickname ORDER BY date DESC' # ); my($friends, $journals, $ids, %data); $friends = $self->sqlSelectAll( 'u.nickname, j.friend, MAX(jo.id) as id', 'journals as jo, journal_friends as j, users as u', "j.uid = $uid AND j.friend = u.uid AND j.friend = jo.uid", 'GROUP BY u.nickname' ); return [] unless @$friends; for my $friend (@$friends) { $ids .= "id = $friend->[2] OR "; $data{$friend->[2]} = [ @$friend[0, 1] ]; } $ids =~ s/ OR $//; $journals = $self->sqlSelectAll( 'date, description, id', 'journals', $ids ); for my $journal (@$journals) { # tack on the extra data @{$data{$journal->[2]}}[2 .. 4] = @{$journal}[0 .. 2]; } # pull it all back together return [ map { $data{$_} } sort { $b <=> $a } keys %data ]; } sub message_friends { my($self) = @_; my $code = MSG_CODE_JOURNAL_FRIEND; my $uid = $ENV{SLASH_USER}; my $cols = "jf.uid"; my $table = "journal_friends AS jf, users_param AS up1, users_param AS up2"; my $where = "jf.friend=$uid AND jf.uid=up1.uid AND jf.uid=up2.uid AND up1.name = 'deliverymodes' AND up1.value >= 0 AND up2.name = 'messagecodes_$code' AND up2.value = 1"; my $friends = $self->sqlSelectColArrayref($cols, $table, $where); return $friends; } sub add { my($self, $friend) = @_; my $uid = $ENV{SLASH_USER}; $self->sqlDo("INSERT INTO journal_friends (uid,friend) VALUES ($uid, $friend)"); } sub is_friend { my($self, $friend) = @_; my $uid = $ENV{SLASH_USER}; return 0 unless $uid && $friend; my $cols = "jf.uid"; my $table = "journal_friends AS jf"; my $where = "jf.uid=$uid AND jf.friend=$friend"; my $is_friend = $self->sqlSelect($cols, $table, $where); return $is_friend; } sub delete { my($self, $friend) = @_; my $uid = $ENV{SLASH_USER}; $self->sqlDo("DELETE FROM journal_friends WHERE uid=$uid AND friend=$friend"); } sub top { my($self, $limit) = @_; $limit ||= getCurrentStatic('journal_top') || 10; my $sql; $sql .= "SELECT count(j.uid) as c, u.nickname, j.uid, max(date)"; $sql .= " FROM journals as j,users as u WHERE "; $sql .= " j.uid = u.uid"; $sql .= " GROUP BY u.nickname ORDER BY c DESC"; $sql .= " LIMIT $limit"; $self->sqlConnect; my $losers = $self->{_dbh}->selectall_arrayref($sql); return $losers; } sub topFriends { # this should only return users who have journal entries -- pudge my($self, $limit) = @_; $limit ||= getCurrentStatic('journal_top') || 10; my $sql; $sql .= " SELECT count(friend) as c, nickname, friend "; $sql .= " FROM journal_friends, users "; $sql .= " WHERE friend=users.uid "; $sql .= " GROUP BY nickname "; $sql .= " ORDER BY c DESC "; $self->sqlConnect; my $losers = $self->{_dbh}->selectall_arrayref($sql); $sql = "SELECT max(date) FROM journals WHERE uid="; for (@$losers) { my $date = $self->{_dbh}->selectrow_array($sql . $_->[2]); push @$_, $date; } return $losers; } sub topRecent { my($self, $limit) = @_; $limit ||= getCurrentStatic('journal_top') || 10; my $sql; $sql .= " SELECT count(jo.id), u.nickname, u.uid, MAX(jo.date) as date "; $sql .= " FROM journals as jo ,users as u "; $sql .= " WHERE jo.uid=u.uid "; $sql .= " GROUP BY u.nickname "; $sql .= " ORDER BY date DESC "; $sql .= " LIMIT $limit"; $self->sqlConnect; my $losers = $self->{_dbh}->selectall_arrayref($sql); return $losers; } sub themes { my($self) = @_; my $uid = $ENV{SLASH_USER}; my $sql; $sql .= "SELECT name from journal_themes"; $self->sqlConnect; my $themes = $self->{_dbh}->selectcol_arrayref($sql); return $themes; } sub searchUsers { my($self, $nickname) = @_; my $slashdb = getCurrentDB(); if (my $uid = $slashdb->getUserUID($nickname)) { if ($self->sqlSelect('uid', 'journals', "uid=$uid")) { return $uid; } else { return $slashdb->getUser($uid); } } my($search, $find, $uids, $jusers, $ids, $journals, @users); $search = getObject("Slash::Search") or return; $find = $search->findUsers( {query => $nickname}, 0, getCurrentStatic('search_default_display') + 1 ); return unless @$find; $uids = join(" OR ", map { "uid=$_->[2]" } @$find); $jusers = $self->sqlSelectAllHashref( 'uid', 'uid, MAX(id) as id', 'journals', $uids, 'GROUP BY uid' ); $ids = join(" OR ", map { "id=$_->{id}" } values %$jusers); $journals = $self->sqlSelectAllHashref( 'uid', 'uid, id, date, description', 'journals', $ids ); for my $user (sort { lc $a->[1] cmp lc $b->[1] } @$find) { my $uid = $user->[2]; my $nick = $user->[1]; if (exists $journals->{$uid}) { push @users, [ $nick, $uid, $journals->{$uid}{date}, $journals->{$uid}{description}, $journals->{$uid}{id}, ]; } else { push @users, [$nick, $uid]; } } return \@users; } sub get { my($self, $id, $val) = @_; my $answer; if ((ref($val) eq 'ARRAY')) { # the grep was failing before, is this right? my @articles = grep /^comment$/, @$val; my @other = grep !/^comment$/, @$val; if (@other) { my $values = join ',', @other; $answer = $self->sqlSelectHashref($values, 'journals', "id=$id"); } if (@articles) { $answer->{comment} = $self->sqlSelect('article', 'journals', "id=$id"); } } elsif ($val) { if ($val eq 'article') { ($answer) = $self->sqlSelect('article', 'journals', "id=$id"); } else { ($answer) = $self->sqlSelect($val, 'journals', "id=$id"); } } else { $answer = $self->sqlSelectHashref('*', 'journals', "id=$id"); ($answer->{article}) = $self->sqlSelect('article', 'journals_text', "id=$id"); } return $answer; } sub DESTROY { my($self) = @_; $self->{_dbh}->disconnect if !$ENV{GATEWAY_INTERFACE} && $self->{_dbh}; } 1; __END__ # Below is the stub of documentation for your module. You better edit it! =head1 NAME Slash::Journal - Journal system splace =head1 SYNOPSIS use Slash::Journal; =head1 DESCRIPTION This is a port of Tangent's journal system. Blah blah blah. =head1 AUTHOR Brian Aker, brian@tangent.org =head1 SEE ALSO perl(1). =cut