Initial checkin.
Signed-off-by: Thomas Hochstein <thh@thh.name>
This commit is contained in:
commit
30132626b8
68 changed files with 5497 additions and 0 deletions
478
MOD/DBIUtilsPublic.pm
Normal file
478
MOD/DBIUtilsPublic.pm
Normal file
|
|
@ -0,0 +1,478 @@
|
|||
######################################################################
|
||||
#
|
||||
# $Id: DBIUtilsPublic.pm 267 2010-05-27 19:46:57Z alba $
|
||||
#
|
||||
# Copyright 2007 - 2009 Roman Racine
|
||||
# Copyright 2009 Alexander Bartolich
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
######################################################################
|
||||
package MOD::DBIUtilsPublic;
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
use DBI;
|
||||
use News::Article;
|
||||
use Carp qw(confess);
|
||||
use Time::Local;
|
||||
|
||||
sub display_single;
|
||||
sub set_status;
|
||||
sub set_status_by_moderator;
|
||||
sub displayrange;
|
||||
sub get_working_by_id;
|
||||
sub get_reason;
|
||||
sub set_rejected;
|
||||
sub get_statistics;
|
||||
|
||||
# 'spam' can be put back to 'pending' queue
|
||||
# 'moderated' tells poster.pl to send the message via NNTP (there is
|
||||
# no safe way to undo this)
|
||||
# 'rejected' means that a mail was sent the poster - cannot be undone
|
||||
# 'deleted' can be put back to 'pending' queue
|
||||
# 'posted' means that message was sent to server - cannot be undone
|
||||
|
||||
use constant NOT_FINAL =>
|
||||
"status <> 'rejected' AND status <> 'posted' AND status <> 'sending'";
|
||||
|
||||
######################################################################
|
||||
# Constructor, open a new connection to the database
|
||||
######################################################################
|
||||
sub new($$)
|
||||
######################################################################
|
||||
{
|
||||
my ($class,$configref) = @_;
|
||||
my $self = {};
|
||||
$self->{'config'} = $configref;
|
||||
$self->{'dsn'} = "DBI:mysql:database=$self->{'config'}->{'mysql_db'};host=$self->{'config'}->{'mysql_host'};port=$self->{'config'}->{'mysql_port'}";
|
||||
$self->{'dbh'} = DBI->connect($self->{'dsn'},$self->{'config'}->{'mysql_username'},$self->{'config'}->{'mysql_password'},
|
||||
{ RaiseError => 1})
|
||||
or die($DBI::errstr);
|
||||
|
||||
bless $self,$class;
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
||||
##Die nachfolgenden Methoden sind fuer den Gebrauch im Webinterface bestimmt, alle Methoden, die den Zustand der DB
|
||||
##aendern, muessen idempotent sein!
|
||||
|
||||
######################################################################
|
||||
# Update the Status of a posting
|
||||
######################################################################
|
||||
sub set_status($$$$)
|
||||
######################################################################
|
||||
{
|
||||
my ($self, $id, $newstatus, $prevstatus) = @_;
|
||||
my $table = $self->{'config'}->{'mysql_table'} || confess;
|
||||
|
||||
my $query =
|
||||
"UPDATE $table" .
|
||||
"\nSET status=(?)" .
|
||||
"\nWHERE id=(?)";
|
||||
if ($prevstatus)
|
||||
{
|
||||
$query .= "\nAND (\n status = '";
|
||||
$query .= join("'\n OR status = '", @$prevstatus);
|
||||
$query .= "'\n)";
|
||||
}
|
||||
else
|
||||
{
|
||||
$query .= "\nAND " . NOT_FINAL;
|
||||
}
|
||||
|
||||
my $stmt = $self->{'dbh'}->prepare($query);
|
||||
return $stmt->execute($newstatus, $id);
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Update the Status of a posting
|
||||
######################################################################
|
||||
sub set_status_by_moderator()
|
||||
######################################################################
|
||||
{
|
||||
my ($self, $newstatus, $id, $moderator) = @_;
|
||||
my $table = $self->{'config'}->{'mysql_table'} || confess;
|
||||
|
||||
$self->{'dbh'}->do(
|
||||
"UPDATE $table" .
|
||||
"\nSET status=(?), Moderator=(?), Moddatum=NOW()" .
|
||||
"\nWHERE id=(?)" .
|
||||
"\nAND " . NOT_FINAL,
|
||||
undef, $newstatus, $moderator, $id
|
||||
);
|
||||
}
|
||||
|
||||
######################################################################
|
||||
sub set_rejected($$$$$)
|
||||
######################################################################
|
||||
{
|
||||
my ($self, $newstatus, $article_id, $moderator, $reply) = @_;
|
||||
my $table = $self->{'config'}->{'mysql_table'} || confess;
|
||||
|
||||
$self->set_status_by_moderator($newstatus, $article_id, $moderator);
|
||||
|
||||
my $query = sprintf(
|
||||
"INSERT INTO %s_reply\n" .
|
||||
"(article_id, reply_date, reply_message)\n" .
|
||||
"VALUES (?, NOW(), ?)\n" .
|
||||
"ON DUPLICATE KEY UPDATE\n" .
|
||||
" reply_date = NOW(),\n" .
|
||||
" reply_message=(?)",
|
||||
$table
|
||||
);
|
||||
my $stmt = $self->{'dbh'}->prepare($query);
|
||||
$stmt->execute($article_id, $reply, $reply);
|
||||
}
|
||||
|
||||
######################################################################
|
||||
sub set_reply($$$)
|
||||
######################################################################
|
||||
{
|
||||
my ($self, $article_id, $reply) = @_;
|
||||
my $table = $self->{'config'}->{'mysql_table'} || confess;
|
||||
|
||||
my $query = sprintf(
|
||||
"INSERT INTO %s_reply\n" .
|
||||
"(article_id, reply_date, reply_message)\n" .
|
||||
"VALUES (?, NOW(), ?)\n" .
|
||||
"ON DUPLICATE KEY UPDATE\n" .
|
||||
" reply_date = NOW(),\n" .
|
||||
" reply_message=(?)",
|
||||
$table
|
||||
);
|
||||
my $stmt = $self->{'dbh'}->prepare($query);
|
||||
$stmt->execute($article_id, $reply, $reply);
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Display a range out of a table
|
||||
######################################################################
|
||||
sub displayrange($$$$$)
|
||||
######################################################################
|
||||
{
|
||||
my ($self,$status,$start,$number_of_results,$overviewref) = @_;
|
||||
$start = 0 if ($start !~ /^\d+$/);
|
||||
$number_of_results = 1 if ($number_of_results !~ /^\d+$/);
|
||||
|
||||
my $table = $self->{'config'}->{'mysql_table'}
|
||||
|| confess 'No "mysql_table" in config';
|
||||
|
||||
my $query = sprintf(
|
||||
"SELECT %s" .
|
||||
"\nFROM %s" .
|
||||
"\nWHERE status=(?)" .
|
||||
"\nORDER BY ID DESC" .
|
||||
"\nLIMIT %d,%d",
|
||||
join(',', @$overviewref),
|
||||
$table,
|
||||
$start, $number_of_results
|
||||
);
|
||||
|
||||
my $stmt = $self->{'dbh'}->prepare($query);
|
||||
$stmt->execute($status);
|
||||
return $stmt;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# display a single entry of a table
|
||||
######################################################################
|
||||
sub display_single($$$)
|
||||
######################################################################
|
||||
{
|
||||
my ($self,$status,$id) = @_;
|
||||
|
||||
my $table = $self->{'config'}->{'mysql_table'} || confess;
|
||||
|
||||
my $query =
|
||||
"SELECT CONCAT(header, \"\\n\\n\", body)," .
|
||||
"\n Status," .
|
||||
"\n Spamcount," .
|
||||
"\n Moderator," .
|
||||
"\n Moddatum AS 'Decision Date'," .
|
||||
"\n Flag" .
|
||||
"\nFROM $table" .
|
||||
"\nWHERE id=(?)";
|
||||
my @param = ( $id );
|
||||
|
||||
if ($status)
|
||||
{
|
||||
$query .= "\nAND Status=(?)";
|
||||
push @param, $status;
|
||||
}
|
||||
|
||||
my $stmt = $self->{'dbh'}->prepare($query);
|
||||
$stmt->execute(@param);
|
||||
return $stmt;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
sub set_status_posted($$$)
|
||||
######################################################################
|
||||
{
|
||||
my ($self,$id,$user) = @_;
|
||||
return $self->set_status_by_moderator('moderated', $id, $user);
|
||||
}
|
||||
|
||||
######################################################################
|
||||
sub get_working_by_id($$)
|
||||
######################################################################
|
||||
{
|
||||
my ($self,$id) = @_;
|
||||
my $table = $self->{'config'}->{'mysql_table'} || confess;
|
||||
my $query = $self->{'dbh'}->prepare(
|
||||
"SELECT" .
|
||||
"\n CONCAT(header,\"\\n\\n\",body) AS Posting," .
|
||||
"\n if (length(replyto) > 1,replyto,sender) AS Adresse" .
|
||||
"\nFROM $table" .
|
||||
"\nWHERE ID=(?)" .
|
||||
"\nAND " . NOT_FINAL
|
||||
);
|
||||
$query->execute($id);
|
||||
return $query;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
sub get_reason($$)
|
||||
######################################################################
|
||||
{
|
||||
my ($self,$id) = @_;
|
||||
my $table = $self->{'config'}->{'mysql_table'} || confess;
|
||||
|
||||
my $query = $self->{'dbh'}->prepare(
|
||||
"SELECT reply_message" .
|
||||
"\nFROM ${table}, ${table}_reply" .
|
||||
"\nWHERE ${table}.id = ${table}_reply.article_id" .
|
||||
"\nAND article_id=(?)" .
|
||||
"\nAND (status='rejected' OR status='deleted')
|
||||
");
|
||||
$query->execute($id);
|
||||
return $query;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
sub display_errors($$$$$)
|
||||
######################################################################
|
||||
{
|
||||
my ($self,$status,$start,$number_of_results,$overviewref) = @_;
|
||||
$start = 0 if ($start !~ /^\d+$/);
|
||||
$number_of_results = 1 if ($number_of_results !~ /^\d+$/);
|
||||
|
||||
my $table = $self->{'config'}->{'mysql_table'} || confess;
|
||||
|
||||
my $query = sprintf(
|
||||
"SELECT %s" .
|
||||
"\nFROM %s_error_view" .
|
||||
"\nORDER BY error_date DESC" .
|
||||
"\nLIMIT %d, %d",
|
||||
join(',', @$overviewref),
|
||||
$table,
|
||||
$start, $number_of_results
|
||||
);
|
||||
my $stmt = $self->{'dbh'}->prepare($query);
|
||||
$stmt->execute();
|
||||
return $stmt;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
sub get_errormessage($$)
|
||||
######################################################################
|
||||
{
|
||||
my ($self,$id) = @_;
|
||||
|
||||
my $table = $self->{'config'}->{'mysql_table'} || confess;
|
||||
|
||||
my $query = sprintf(
|
||||
"SELECT error_message" .
|
||||
"\nFROM %s_error" .
|
||||
"\nWHERE error_id=(?)",
|
||||
$table
|
||||
);
|
||||
my $stmt = $self->{'dbh'}->prepare($query);
|
||||
$stmt->execute($id);
|
||||
return $stmt;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
sub invert_flag($$)
|
||||
######################################################################
|
||||
{
|
||||
my ($self,$id) = @_;
|
||||
my $table = $self->{'config'}->{'mysql_table'} || confess;
|
||||
$self->{'dbh'}->do(
|
||||
"UPDATE $table" .
|
||||
"\nSET flag = !flag" .
|
||||
"\nWHERE ID=(?)" .
|
||||
"\nAND " . NOT_FINAL,
|
||||
undef, $id
|
||||
);
|
||||
}
|
||||
|
||||
######################################################################
|
||||
sub calc_item_stats($$)
|
||||
######################################################################
|
||||
{
|
||||
my ($r_result, $r_items) = @_;
|
||||
|
||||
my @items = sort { $a <=> $b }( @$r_items );
|
||||
return undef unless($#items >= 0);
|
||||
|
||||
my $sum = 0;
|
||||
for my $i( @items ) { $sum += $i; }
|
||||
|
||||
my $nr_items = 1 + $#items;
|
||||
my $pivot = int($nr_items / 2);
|
||||
my $median = $items[$pivot];
|
||||
if (($nr_items % 2) == 0)
|
||||
{
|
||||
$median = ( $median + $items[$pivot - 1] ) / 2;
|
||||
}
|
||||
|
||||
$r_result->{'count'} = $nr_items;
|
||||
$r_result->{'sum'} = $sum;
|
||||
$r_result->{'avg'} = $sum / $nr_items;
|
||||
$r_result->{'median'} = $median;
|
||||
$r_result->{'min'} = $items[0];
|
||||
$r_result->{'max'} = $items[ $#items ];
|
||||
|
||||
return $r_items;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
sub get_reaction_time($;$$$)
|
||||
######################################################################
|
||||
{
|
||||
my ( $self, $from, $to, $status ) = @_;
|
||||
|
||||
# Warning: Plain "Moddatum - Datum" returns strange values when
|
||||
# crossing day boundaries. Using unix_timestamp instead.
|
||||
|
||||
my $query =
|
||||
"select unix_timestamp(Datum), timestampdiff(SECOND, Datum, Moddatum)" .
|
||||
"\nfrom " . $self->{'config'}->{'mysql_table'} .
|
||||
"\nwhere datum is not null" .
|
||||
"\nand Moddatum is not null" .
|
||||
"\nand Datum is not null";
|
||||
|
||||
if ($from)
|
||||
{ $query .= "\nand datum >= from_unixtime($from)"; }
|
||||
if ($to)
|
||||
{ $query .= "\nand datum < from_unixtime($to)"; }
|
||||
if ($status)
|
||||
{ $query .= "\nand Status = '$status'"; }
|
||||
|
||||
my $sth = $self->{'dbh'}->prepare($query);
|
||||
$sth->execute();
|
||||
|
||||
my %result;
|
||||
while(my $row = $sth->fetchrow_arrayref )
|
||||
{
|
||||
my $datum = 0 + $row->[0];
|
||||
my $reaction_time = 0 + $row->[1];
|
||||
my ($sec, $minute, $hour, $mday, $month, $year, $wday, $yday, $isdst) =
|
||||
localtime($datum);
|
||||
|
||||
my $y = sprintf("%04d", $year + 1900);
|
||||
my $m = sprintf("%02d", $month + 1);
|
||||
my $d = sprintf("%02d", $mday);
|
||||
|
||||
my $items = $result{$y}->{$m}->{$d}->{'items'};
|
||||
if (defined( $items ))
|
||||
{
|
||||
push @$items, $reaction_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
$result{$y}->{$m}->{$d}->{'items'} = [ $reaction_time ];
|
||||
}
|
||||
}
|
||||
|
||||
# we are going to modify the hash so we need robust iteration
|
||||
my @year = keys(%result);
|
||||
my @all_items;
|
||||
|
||||
for my $year(@year)
|
||||
{
|
||||
my $r_month = $result{$year};
|
||||
my @month = keys(%$r_month);
|
||||
my @year_items;
|
||||
|
||||
for my $month(@month)
|
||||
{
|
||||
my $r_mday = $r_month->{$month};
|
||||
my @mday = keys(%$r_mday);
|
||||
my @month_items;
|
||||
|
||||
for my $mday(@mday)
|
||||
{
|
||||
my $r = $r_mday->{$mday};
|
||||
my $r_items = $r->{'items'};
|
||||
push @month_items, @$r_items;
|
||||
calc_item_stats($r, $r_items);
|
||||
# delete $r->{'items'};
|
||||
}
|
||||
|
||||
push @year_items, @month_items;
|
||||
calc_item_stats($r_mday->{'total'} = {}, \@month_items);
|
||||
}
|
||||
push @all_items, @year_items;
|
||||
calc_item_stats($r_month->{'total'} = {}, \@year_items);
|
||||
}
|
||||
calc_item_stats($result{'total'} = {}, \@all_items);
|
||||
|
||||
return \%result;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
sub get_statistics($)
|
||||
######################################################################
|
||||
{
|
||||
my ($self) = @_;
|
||||
my $dbh = $self->{'dbh'}
|
||||
|| confess 'No "dbh" in self';
|
||||
my $table = $self->{'config'}->{'mysql_table'} || confess;
|
||||
|
||||
#
|
||||
# Warning: The combination of union and selectall_arrayref does not
|
||||
# like null values. They are just ommitted from the result.
|
||||
#
|
||||
my $arrayref = $dbh->selectall_arrayref(
|
||||
"select unix_timestamp(min(datum)) from $table" .
|
||||
"\nunion" .
|
||||
"\nselect unix_timestamp(max(datum)) from $table"
|
||||
);
|
||||
|
||||
if (!$arrayref) { return undef; }
|
||||
if (!$arrayref->[1]) { return undef; }
|
||||
if (!$arrayref->[0]) { return undef; }
|
||||
|
||||
# add 1 because query is (datum >= min and datum < max)
|
||||
my $to = 1 + $arrayref->[1]->[0];
|
||||
my $from = $arrayref->[0]->[0];
|
||||
undef $arrayref;
|
||||
|
||||
my $result = {
|
||||
'all' => $self->get_reaction_time($from, $to)
|
||||
};
|
||||
for my $status(
|
||||
'pending',
|
||||
'moderated',
|
||||
'spam',
|
||||
'rejected',
|
||||
'deleted',
|
||||
'posted',
|
||||
'sending')
|
||||
{
|
||||
$result->{$status} = $self->get_reaction_time($from, $to, $status);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
######################################################################
|
||||
1;
|
||||
######################################################################
|
||||
Loading…
Add table
Add a link
Reference in a new issue