Initial commit.
This commit is contained in:
206
lib/perl5/Selima/Guestbook.pm
Normal file
206
lib/perl5/Selima/Guestbook.pm
Normal file
@@ -0,0 +1,206 @@
|
||||
# Selima Website Content Management System
|
||||
# Guestbook.pm: The guestbook-related subroutines.
|
||||
|
||||
# Copyright (c) 2004-2018 imacat.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# Author: imacat <imacat@mail.imacat.idv.tw>
|
||||
# First written: 2004-10-23
|
||||
|
||||
package Selima::Guestbook;
|
||||
use 5.008;
|
||||
use strict;
|
||||
use warnings;
|
||||
use base qw(Exporter);
|
||||
use vars qw(@EXPORT @EXPORT_OK);
|
||||
BEGIN {
|
||||
@EXPORT = qw(update_pageno);
|
||||
@EXPORT_OK = @EXPORT;
|
||||
# Prototype declaration
|
||||
sub update_pageno($$$;$);
|
||||
sub split_page(\@\%$;$);
|
||||
sub update_old_gbpageno($$;$);
|
||||
}
|
||||
|
||||
use Selima::DataVars qw($DBH);
|
||||
use Selima::Format;
|
||||
|
||||
# update_pageno: Update the guestbook page number
|
||||
sub update_pageno($$$;$) {
|
||||
local ($_, %_);
|
||||
my ($table, $page_size, $cols, $from, $sql, $sth, $count, $row, $len, $where);
|
||||
my (@ents, %sizes, %orig, %pagenos, $startno, $startat, $commit);
|
||||
($table, $page_size, $cols, $from) = @_;
|
||||
|
||||
# If we should begin and commit here
|
||||
$commit = $DBH->{"AutoCommit"};
|
||||
$DBH->begin_work if $commit;
|
||||
|
||||
# Update the current page number
|
||||
# Check the page to start from
|
||||
undef $startno;
|
||||
undef $startat;
|
||||
$from = fmttime $from if defined $from;
|
||||
if (defined $from) {
|
||||
$sql = "SELECT pageno FROM $table WHERE NOT hid AND created<'$from'"
|
||||
. " ORDER BY created DESC LIMIT 1;\n";
|
||||
$sth = $DBH->prepare($sql);
|
||||
$sth->execute;
|
||||
undef $from if $sth->rows != 1;
|
||||
}
|
||||
if (defined $from) {
|
||||
$startno = ${$sth->fetch}[0];
|
||||
undef $sth;
|
||||
$sql = "SELECT created FROM $table WHERE NOT hid AND pageno=$startno"
|
||||
. " ORDER BY created LIMIT 1;\n";
|
||||
$sth = $DBH->prepare($sql);
|
||||
$sth->execute;
|
||||
$startat = ${$sth->fetch}[0];
|
||||
}
|
||||
@_ = qw();
|
||||
push @_, "created>='" . fmttime($startat) . "'" if defined $startat;
|
||||
$where = (@_ > 0)? " WHERE " . join(" AND ", @_): "";
|
||||
# Ge the size of everyhing
|
||||
$len = join " + ", map "CASE WHEN $_ IS NULL THEN 0 ELSE char_length($_) END", @$cols;
|
||||
$len = "CASE WHEN hid THEN 0 ELSE $len END AS len";
|
||||
$sql = "SELECT sn, $len, pageno FROM $table $where ORDER BY created;\n";
|
||||
$sth = $DBH->prepare($sql);
|
||||
$sth->execute;
|
||||
$count = $sth->rows;
|
||||
for ($_ = 0, @ents = qw(), %sizes = qw(), %orig = qw(); $_ < $count; $_++) {
|
||||
$row = $sth->fetchrow_hashref;
|
||||
push @ents, $$row{"sn"};
|
||||
$sizes{$$row{"sn"}} = $$row{"len"};
|
||||
$orig{$$row{"sn"}} = $$row{"pageno"};
|
||||
}
|
||||
# Split page
|
||||
%pagenos = split_page @ents, %sizes, $page_size, $startno;
|
||||
# Update it
|
||||
foreach (@ents) {
|
||||
next if $orig{$_} == $pagenos{$_};
|
||||
$sql = "UPDATE $table SET pageno=$pagenos{$_} WHERE sn=$_;\n";
|
||||
$DBH->gdo($sql);
|
||||
}
|
||||
|
||||
# Update the old page number
|
||||
# No need to update it anymore. Let it go.
|
||||
$DBH->commit if $commit;
|
||||
return;
|
||||
}
|
||||
|
||||
# split_page: Split page according to the entry sizes
|
||||
sub split_page(\@\%$;$) {
|
||||
local ($_, %_);
|
||||
my ($ents, $sizes, $page_size, $startno, $cursize, %pagenos);
|
||||
($ents, $sizes, $page_size, $startno) = @_;
|
||||
$startno = 1 if !defined $startno;
|
||||
|
||||
# Bounce for nothing
|
||||
return if scalar @$ents == 0;
|
||||
|
||||
# Split pages
|
||||
%pagenos = qw();
|
||||
$pagenos{$$ents[0]} = $startno;
|
||||
$cursize = $$sizes{$$ents[0]};
|
||||
for ($_ = 1; $_ < scalar(@$ents); $_++) {
|
||||
my ($hi_gap, $lo_gap);
|
||||
# We need at least one record
|
||||
if ($cursize == 0) {
|
||||
$pagenos{$$ents[$_]} = $pagenos{$$ents[$_-1]};
|
||||
$cursize += $$sizes{$$ents[$_]};
|
||||
next;
|
||||
# Not oversized yet
|
||||
} elsif ($cursize + $$sizes{$$ents[$_]} < $page_size) {
|
||||
$pagenos{$$ents[$_]} = $pagenos{$$ents[$_-1]};
|
||||
$cursize += $$sizes{$$ents[$_]};
|
||||
next;
|
||||
}
|
||||
$hi_gap = $cursize + $$sizes{$$ents[$_]} - $page_size;
|
||||
$lo_gap = $page_size - $cursize;
|
||||
# The upper boundary is closer, and the page is not too oversized
|
||||
if ($hi_gap < $lo_gap && $hi_gap <= $page_size / 4) {
|
||||
$pagenos{$$ents[$_]} = $pagenos{$$ents[$_-1]};
|
||||
$cursize += $$sizes{$$ents[$_]};
|
||||
# Or, we prefer the lower, since the page is not oversized
|
||||
} else {
|
||||
$pagenos{$$ents[$_]} = $pagenos{$$ents[$_-1]} + 1;
|
||||
$cursize = $$sizes{$$ents[$_]};
|
||||
}
|
||||
}
|
||||
|
||||
return %pagenos;
|
||||
}
|
||||
|
||||
# update_old_gbpageno: Update the old guestbook page number
|
||||
sub update_old_gbpageno($$;$) {
|
||||
local ($_, %_);
|
||||
my ($table, $page_size, $from, $sql, $sth, $count, $row, $len, $cond);
|
||||
my (@ents, %sizes, %orig, %pagenos, $startno, $startat, $commit);
|
||||
($table, $page_size, $from) = @_;
|
||||
|
||||
# If we should begin and commit here
|
||||
$commit = $DBH->{"AutoCommit"};
|
||||
$DBH->begin_work if $commit;
|
||||
|
||||
# Update the old page number
|
||||
undef $startno;
|
||||
undef $startat;
|
||||
if (defined $from) {
|
||||
$sql = "SELECT oldpageno FROM $table WHERE NOT hid AND created<'$from'"
|
||||
. " ORDER BY created DESC LIMIT 1;\n";
|
||||
$sth = $DBH->prepare($sql);
|
||||
$sth->execute;
|
||||
$startno = ${$sth->fetch}[0];
|
||||
undef $sth;
|
||||
$sql = "SELECT created FROM $table WHERE NOT hid AND oldpageno=$startno"
|
||||
. " ORDER BY created LIMIT 1;\n";
|
||||
$sth = $DBH->prepare($sql);
|
||||
$sth->execute;
|
||||
$startat = ${$sth->fetch}[0];
|
||||
}
|
||||
@_ = qw();
|
||||
push @_, "NOT hid";
|
||||
push @_, "created>='$startat'" if defined $startat;
|
||||
$cond = join " AND ", @_;
|
||||
# Ge the size of everyhing
|
||||
$len = "${table}_oldlen(created, ip, host, name, identity, location, email, url, message, updated, updatedby) AS len";
|
||||
# Tavern Backalley has a special table structure
|
||||
$len = "garbage_oldlen(created, ip, host, message, updated, updatedby) AS len"
|
||||
if $table eq "garbage";
|
||||
$sql = "SELECT sn, $len, oldpageno FROM $table WHERE $cond ORDER BY created;\n";
|
||||
$sth = $DBH->prepare($sql);
|
||||
$sth->execute;
|
||||
$count = $sth->rows;
|
||||
for ($_ = 0, @ents = qw(), %sizes = qw(), %orig = qw(); $_ < $count; $_++) {
|
||||
$row = $sth->fetchrow_hashref;
|
||||
push @ents, $$row{"sn"};
|
||||
$sizes{$$row{"sn"}} = $$row{"len"};
|
||||
$orig{$$row{"sn"}} = $$row{"oldpageno"};
|
||||
}
|
||||
# Split page
|
||||
# Old page size is always 10240
|
||||
%pagenos = split_page @ents, %sizes, 10240, $startno;
|
||||
# Update it
|
||||
foreach (@ents) {
|
||||
next if $orig{$_} == $pagenos{$_};
|
||||
$sql = "UPDATE $table SET oldpageno=$pagenos{$_} WHERE sn=$_;\n";
|
||||
$DBH->gdo($sql);
|
||||
}
|
||||
|
||||
$DBH->commit if $commit;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return 1;
|
||||
Reference in New Issue
Block a user