437 lines
14 KiB
Perl
437 lines
14 KiB
Perl
# Mandy Wu's Website
|
|
# Rebuild.pm: The subroutines to rebuild the web pages.
|
|
|
|
# Copyright (c) 2006-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: 2006-11-14
|
|
|
|
package Selima::emandy::Rebuild;
|
|
use 5.008;
|
|
use strict;
|
|
use warnings;
|
|
use base qw(Exporter);
|
|
use vars qw(@EXPORT @EXPORT_OK);
|
|
BEGIN {
|
|
@EXPORT = qw(rebuild_all rebuild_pages rebuild_links rebuild_legend compose_page);
|
|
@EXPORT_OK = @EXPORT;
|
|
# Prototype declaration
|
|
sub rebuild_all();
|
|
sub rebuild_pages(;$);
|
|
sub rebuild_links(;$);
|
|
sub rebuild_legend(;$);
|
|
sub compose_page($;$);
|
|
}
|
|
|
|
use Config qw(%Config);
|
|
use Data::Dumper qw();
|
|
use Fcntl qw(:flock);
|
|
use File::Basename qw(basename);
|
|
use IO::NestedCapture qw(CAPTURE_STDOUT);
|
|
use Lingua::ZH::Numbers;
|
|
|
|
use Selima::DataVars qw($DBH :output :rebuild :requri);
|
|
use Selima::GetLang;
|
|
use Selima::Guest;
|
|
use Selima::PageFunc;
|
|
use Selima::ShortCut;
|
|
|
|
use Selima::emandy::HTML;
|
|
|
|
use vars qw($PKGL10N);
|
|
|
|
# rebuild_all: Rebuild everything
|
|
sub rebuild_all() {
|
|
local ($_, %_);
|
|
# Lock the required tables
|
|
$DBH->lock(map { $_ => LOCK_SH } @REBUILD_TABLES);
|
|
# Rebuild the pages
|
|
rebuild_pages;
|
|
# Rebuild the links
|
|
rebuild_links;
|
|
# Rebuild the legend
|
|
rebuild_legend;
|
|
# Rebuild the index
|
|
# To be done
|
|
#rebuild_index;
|
|
return;
|
|
}
|
|
|
|
# rebuild_pages: Rebuild the pages
|
|
sub rebuild_pages(;$) {
|
|
local ($_, %_);
|
|
my ($sql, $sth, $count, $rebuild_everything);
|
|
my $lang;
|
|
$sql = $_[0];
|
|
|
|
$lang = getlang;
|
|
|
|
# Rebuild everything
|
|
$rebuild_everything = !defined $sql;
|
|
if ($rebuild_everything) {
|
|
$sql = "SELECT * FROM pages"
|
|
. " WHERE NOT hid;\n";
|
|
}
|
|
|
|
$sth = $DBH->prepare($sql);
|
|
$sth->execute;
|
|
$count = $sth->rows;
|
|
# Bounce if no pages to build on a partial rebuild
|
|
# This prevents needless sitemap rebuilding
|
|
return if !$rebuild_everything && $count == 0;
|
|
# Build each page
|
|
for (my $i = 0; $i < $count; $i++) {
|
|
my ($page, $html);
|
|
$page = $sth->fetchrow_hashref;
|
|
# Read the picture into the picture deposit
|
|
# To be done
|
|
|
|
$html = compose_page($page, $lang);
|
|
goutpage $html, $$page{"path"}, $lang
|
|
if defined $html;
|
|
|
|
# Output related pictures only when rebuilding everything
|
|
# To be done
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
# rebuild_links: Rebuild the links
|
|
sub rebuild_links(;$) {
|
|
local ($_, %_);
|
|
my ($sql, $sth, $count, $FD, $rebuild_everything);
|
|
my ($lang, $args, $html);
|
|
$sql = $_[0];
|
|
|
|
$lang = getlang;
|
|
|
|
# Rebuild everything
|
|
$rebuild_everything = !defined $sql;
|
|
if ($rebuild_everything) {
|
|
@_ = $DBH->cols("linkcat");
|
|
push @_, $DBH->strcat("'/links'", "linkcat_path(sn, id, parent)")
|
|
. " AS path";
|
|
$sql = "SELECT " . join(", ", @_) . " FROM linkcat"
|
|
. " WHERE linkcat_isshown(sn, hid, parent);\n";
|
|
}
|
|
|
|
$sth = $DBH->prepare($sql);
|
|
$sth->execute;
|
|
$count = $sth->rows;
|
|
for (my $i = 0; $i < $count; $i++) {
|
|
my ($page, $sql1, $sth1, $count1, $row1);
|
|
$page = $sth->fetchrow_hashref;
|
|
|
|
# Find the ancesters
|
|
@_ = $DBH->cols("linkcat");
|
|
push @_, $DBH->strcat("'/links'", "linkcat_path(sn, id, parent)")
|
|
. " AS path";
|
|
$sql1 = "SELECT " . join(", ", @_) . " FROM linkcat"
|
|
. " WHERE linkcat_ischild(sn, " . $$page{"sn"} . ")"
|
|
. " ORDER BY linkcat_fullord(parent, ord);\n";
|
|
$sth1 = $DBH->prepare($sql1);
|
|
$sth1->execute;
|
|
$count1 = $sth1->rows;
|
|
for (my $i = 0, $$page{"parents"} = []; $i < $count1; $i++) {
|
|
push @{$$page{"parents"}}, $sth1->fetchrow_hashref;
|
|
}
|
|
|
|
# Find the subcategories
|
|
@_ = $DBH->cols("linkcat");
|
|
push @_, $DBH->strcat("'/links'", "linkcat_path(sn, id, parent)")
|
|
. " AS path";
|
|
$sql1 = "SELECT " . join(", ", @_) . " FROM linkcat"
|
|
. " WHERE parent=" . $$page{"sn"}
|
|
. " AND linkcat_isshown(sn, hid, parent)"
|
|
. " ORDER BY ord;\n";
|
|
$sth1 = $DBH->prepare($sql1);
|
|
$sth1->execute;
|
|
$count1 = $sth1->rows;
|
|
for (my $i = 0, $$page{"scats"} = []; $i < $count1; $i++) {
|
|
my ($sql2, $sth2, $row2);
|
|
$row1 = $sth1->fetchrow_hashref;
|
|
# Find the belonging links
|
|
$sql2 = "SELECT count(linkcatz.sn) AS count FROM linkcatz"
|
|
. " INNER JOIN links ON linkcatz.link=links.sn"
|
|
. " INNER JOIN linkcat ON linkcatz.cat=linkcat.sn"
|
|
. " WHERE linkcatz.cat=" . $$row1{"sn"}
|
|
. " AND NOT links.hid;\n";
|
|
$sth2 = $DBH->prepare($sql2);
|
|
$sth2->execute;
|
|
$row2 = $sth2->fetchrow_hashref;
|
|
$$row1{"links"} = $$row2{"count"};
|
|
push @{$$page{"scats"}}, $row1;
|
|
}
|
|
|
|
# Find the belonging links
|
|
@_ = map "links.$_", $DBH->cols("links");
|
|
$sql1 = "SELECT " . join(", ", @_) . " FROM links"
|
|
. " INNER JOIN linkcatz ON linkcatz.link=links.sn"
|
|
. " WHERE linkcatz.cat=" . $$page{"sn"}
|
|
. " AND NOT links.hid;\n";
|
|
$sth1 = $DBH->prepare($sql1);
|
|
$sth1->execute;
|
|
$count1 = $sth1->rows;
|
|
for (my $i = 0, $$page{"links"} = []; $i < $count1; $i++) {
|
|
push @{$$page{"links"}}, $sth1->fetchrow_hashref;
|
|
}
|
|
|
|
$html = compose_page($page, $lang);
|
|
goutpage $html, $$page{"path"}, $lang
|
|
if defined $html;
|
|
}
|
|
|
|
# Build the root index page
|
|
@_ = $DBH->cols("linkcat");
|
|
push @_, $DBH->strcat("'/links'", "linkcat_path(sn, id, parent)")
|
|
. " AS path";
|
|
$sql = "SELECT " . join(", ", @_) . " FROM linkcat"
|
|
. " WHERE parent IS NULL"
|
|
. " AND linkcat_isshown(sn, hid, parent)"
|
|
. " ORDER BY ord;\n";
|
|
$sth = $DBH->prepare($sql);
|
|
$sth->execute;
|
|
$count = $sth->rows;
|
|
for ($_ = 0, @_ = qw(); $_ < $count; $_++) {
|
|
my ($cat, $sql1, $sth1, $count1);
|
|
$cat = $sth->fetchrow_hashref;
|
|
|
|
# Find the belonging links
|
|
$sql1 = "SELECT count(linkcatz.sn) AS count FROM linkcatz"
|
|
. " INNER JOIN links ON linkcatz.link=links.sn"
|
|
. " INNER JOIN linkcat ON linkcatz.cat=linkcat.sn"
|
|
. " WHERE linkcatz.cat=" . $$cat{"sn"}
|
|
. " AND NOT links.hid;\n";
|
|
$sth1 = $DBH->prepare($sql1);
|
|
$sth1->execute;
|
|
$$cat{"links"} = ${$sth1->fetch}[0];
|
|
|
|
push @_, $cat;
|
|
}
|
|
$ALT_PAGE_PARAM = {
|
|
"path" => "/links/",
|
|
"lang" => $lang,
|
|
"keywords" => __("related links"),
|
|
"class" => "links",
|
|
"static" => 1,
|
|
"all_linguas" => [$lang]};
|
|
$args = page_param;
|
|
# Obtain the page
|
|
IO::NestedCapture->start(CAPTURE_STDOUT);
|
|
binmode IO::NestedCapture->instance->{"STDOUT_current"}[-1], ":utf8";
|
|
html_header __("Related Links"), $args;
|
|
html_links_index @_, $args;
|
|
html_footer $args;
|
|
IO::NestedCapture->stop(CAPTURE_STDOUT);
|
|
$FD = IO::NestedCapture->get_last_out;
|
|
$html = join "", <$FD>;
|
|
undef $ALT_PAGE_PARAM;
|
|
goutpage $html, "/links/", $lang;
|
|
|
|
return;
|
|
}
|
|
|
|
# rebuild_legend: Rebuild the legend
|
|
sub rebuild_legend(;$) {
|
|
local ($_, %_);
|
|
my ($start, $sql, $sth, $count, $FD, $page, @pages, $total);
|
|
my ($lang, $args, $html);
|
|
$start = $_[0];
|
|
$start = 1 if !defined $start;
|
|
|
|
$lang = getlang;
|
|
|
|
# Obtain the total number of legend entries
|
|
$_ = "SELECT count(*) FROM legend WHERE NOT hid;\n";
|
|
$sth = $DBH->prepare($_);
|
|
$sth->execute;
|
|
$total = ${$sth->fetch}[0];
|
|
|
|
# Obtain all the available pages numbers
|
|
@_ = qw();
|
|
push @_, "pageno AS no";
|
|
push @_, "legend_page_start(pageno) AS start";
|
|
push @_, "legend_page_end(pageno) AS end";
|
|
$sql = "SELECT " . join(", ", @_) . " FROM legend"
|
|
. " WHERE NOT hid GROUP BY pageno ORDER BY pageno;\n";
|
|
|
|
$sth = $DBH->prepare($sql);
|
|
$sth->execute;
|
|
$count = $sth->rows;
|
|
for (my $i = 0, @pages = qw(); $i < $count; $i++) {
|
|
$page = $sth->fetchrow_hashref;
|
|
$$page{"path"} = sprintf "/legend/%04d.html", $$page{"no"};
|
|
push @pages, $page;
|
|
}
|
|
|
|
# Build each page
|
|
foreach my $page (@pages) {
|
|
next if $$page{"no"} < $start;
|
|
|
|
my ($args, $LIST, $html, $FD);
|
|
Lingua::ZH::Numbers->charset("traditional");
|
|
$_ = number_to_zh($$page{"no"});
|
|
$$page{"title"} = sprintf __("Legend Volume %s"), $_;
|
|
$$page{"kw"} = __("legend");
|
|
$ALT_PAGE_PARAM = {
|
|
"path" => $$page{"path"},
|
|
"lang" => $lang,
|
|
"keywords" => $$page{"kw"},
|
|
"class" => "legend",
|
|
"static" => 1,
|
|
"all_linguas" => [$lang]};
|
|
$args = page_param;
|
|
# Set the list parameter
|
|
$LIST = new Selima::emandy::List::Legend::Public;
|
|
$LIST->{"view"} = "legend_public";
|
|
$LIST->{"pageno"} = $$page{"no"};
|
|
$LIST->{"lastpage"} = ${$pages[$#pages]}{"no"};
|
|
$LIST->{"total"} = $total;
|
|
$args = {%$args, %{$LIST->page_param}};
|
|
# Obtain the page
|
|
IO::NestedCapture->start(CAPTURE_STDOUT);
|
|
binmode IO::NestedCapture->instance->{"STDOUT_current"}[-1], ":utf8";
|
|
html_header $$page{"title"}, $args;
|
|
$LIST->html($args);
|
|
html_footer $args;
|
|
IO::NestedCapture->stop(CAPTURE_STDOUT);
|
|
$FD = IO::NestedCapture->get_last_out;
|
|
$html = join "", <$FD>;
|
|
undef $ALT_PAGE_PARAM;
|
|
goutpage $html, $$page{"path"}, $lang;
|
|
|
|
# Make the symbolic link for the default language
|
|
if (defined $Config{"d_symlink"}) {
|
|
my ($targfile, $linkfile);
|
|
$_ = $$page{"path"};
|
|
$_ .= "index.html" if /\/$/;
|
|
$targfile = basename($_ . ".xhtml");
|
|
$linkfile = "$DOC_ROOT$_.html";
|
|
unless (-l $linkfile && readlink $linkfile eq $targfile) {
|
|
unlink $linkfile if -l $linkfile;
|
|
symlink $targfile, $linkfile;
|
|
}
|
|
}
|
|
}
|
|
|
|
# Make the symbolic link for the latest page
|
|
if (defined $Config{"d_symlink"}) {
|
|
my ($targfile, $linkfile);
|
|
if (@pages > 0) {
|
|
$targfile = sprintf "%04d.html.xhtml",
|
|
${$pages[$#pages]}{"no"};
|
|
} else {
|
|
$targfile = "index.html.xhtml";
|
|
}
|
|
$linkfile = "$DOC_ROOT/legend/latest.html.xhtml";
|
|
unless (-l $linkfile && readlink $linkfile eq $targfile) {
|
|
unlink $linkfile if -l $linkfile;
|
|
symlink $targfile, $linkfile;
|
|
}
|
|
$targfile = "latest.html.xhtml";
|
|
$linkfile = "$DOC_ROOT/legend/latest.html.html";
|
|
unless (-l $linkfile && readlink $linkfile eq $targfile) {
|
|
unlink $linkfile if -l $linkfile;
|
|
symlink $targfile, $linkfile;
|
|
}
|
|
}
|
|
|
|
# Build the root index page
|
|
$ALT_PAGE_PARAM = {
|
|
"path" => "/legend/",
|
|
"lang" => $lang,
|
|
"keywords" => __("legend"),
|
|
"class" => "legend",
|
|
"static" => 1,
|
|
"all_linguas" => [$lang],
|
|
"toc" => ".."};
|
|
if (@pages > 0) {
|
|
$$ALT_PAGE_PARAM{"first"} = "0001.html";
|
|
$$ALT_PAGE_PARAM{"last"} = "latest.html";
|
|
${$pages[$#pages]}{"path"} = "/legend/latest.html";
|
|
}
|
|
$args = page_param;
|
|
# Obtain the page
|
|
IO::NestedCapture->start(CAPTURE_STDOUT);
|
|
binmode IO::NestedCapture->instance->{"STDOUT_current"}[-1], ":utf8";
|
|
html_header __("Legend"), $args;
|
|
html_legend_index @pages, $args;
|
|
html_footer $args;
|
|
IO::NestedCapture->stop(CAPTURE_STDOUT);
|
|
$FD = IO::NestedCapture->get_last_out;
|
|
$html = join "", <$FD>;
|
|
undef $ALT_PAGE_PARAM;
|
|
goutpage $html, "/legend/", $lang;
|
|
|
|
# Make the symbolic link for the default language
|
|
if (defined $Config{"d_symlink"}) {
|
|
my ($targfile, $linkfile);
|
|
$_ = "/legend/index.html";
|
|
$targfile = basename($_ . ".xhtml");
|
|
$linkfile = "$DOC_ROOT$_.html";
|
|
unless (-l $linkfile && readlink $linkfile eq $targfile) {
|
|
unlink $linkfile if -l $linkfile;
|
|
symlink $targfile, $linkfile;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
# compose_page: Compose a page
|
|
sub compose_page($;$) {
|
|
local ($_, %_);
|
|
my ($page, $lang, $args, $FD);
|
|
($page, $lang) = @_;
|
|
$lang = getlang if !defined $lang;
|
|
|
|
$ALT_PAGE_PARAM = {
|
|
"path" => $$page{"path"},
|
|
"lang" => $lang,
|
|
"keywords" => $$page{"kw"},
|
|
"static" => 1,
|
|
"all_linguas" => [$lang]};
|
|
$$ALT_PAGE_PARAM{"preview"} = $page
|
|
if exists $$page{"preview"};
|
|
if (exists $$page{"class"} && defined $$page{"class"} && $$page{"class"} ne "") {
|
|
$$ALT_PAGE_PARAM{"class"} = $$page{"class"};
|
|
} elsif ($$page{"path"} =~ /^\/links\//) {
|
|
$$ALT_PAGE_PARAM{"class"} = "links";
|
|
}
|
|
$args = page_param;
|
|
|
|
# Obtain the page
|
|
IO::NestedCapture->start(CAPTURE_STDOUT);
|
|
binmode IO::NestedCapture->instance->{"STDOUT_current"}[-1], ":utf8";
|
|
html_header $$page{"title"}, $args;
|
|
if ($$page{"path"} =~ /^\/links\/$/) {
|
|
#html_links_index $page, $args;
|
|
} elsif ($$page{"path"} =~ /^\/links\/.+$/) {
|
|
html_links $page, $args;
|
|
} else {
|
|
html_body $page, $args;
|
|
}
|
|
html_footer $args;
|
|
IO::NestedCapture->stop(CAPTURE_STDOUT);
|
|
$FD = IO::NestedCapture->get_last_out;
|
|
$_ = join "", <$FD>;
|
|
|
|
undef $ALT_PAGE_PARAM;
|
|
return $_;
|
|
}
|
|
|
|
return 1;
|