704 lines
25 KiB
Perl
704 lines
25 KiB
Perl
# ==================================================================
|
|
# Plugins::UI - Auto Generated Program Module
|
|
#
|
|
# Plugins::UI
|
|
# Author : Bao Phan
|
|
# Version : 1.0
|
|
# Updated : Tue Mar 15 12:59:20 2016
|
|
#
|
|
# ==================================================================
|
|
#
|
|
|
|
package Plugins::UI;
|
|
# ==================================================================
|
|
|
|
use strict;
|
|
use GT::Base;
|
|
use GT::Plugins qw/STOP CONTINUE/;
|
|
use Links qw/:objects :payment/;
|
|
use Links::Build;
|
|
use Links::SiteHTML;
|
|
|
|
use constants
|
|
VIDEO => 'video',
|
|
PHOTO => 'photo',
|
|
ARTICLE => 'article'
|
|
;
|
|
# Inherit from base class for debug and error methods
|
|
@Plugins::UI::ISA = qw(GT::Base);
|
|
|
|
require Plugins::SlideShow;
|
|
require Plugins::ConvertVideo;
|
|
require GT::SQL::Condition;
|
|
require GT::Date;
|
|
|
|
sub cat_url {
|
|
my $full_name = shift || return;
|
|
|
|
return "$CFG->{build_root_url}/" . $DB->table('Category')->as_url($full_name) . "/" . ($CFG->{build_index_include} ? $CFG->{build_index} : '');
|
|
}
|
|
|
|
sub update_featured_links {
|
|
my ($type, $id, $add) = @_;
|
|
|
|
return if $USER->{Status} ne 'Administrator';
|
|
|
|
return unless $id and $type;
|
|
return if $type !~ /^(article|photo|video)$/i;
|
|
|
|
my $name = $type eq 'article' ? 'featured_articles' : 'featured_photos';
|
|
my $ids = $CFG->{$name} || [];
|
|
|
|
my (@ids, $changed);
|
|
my %ids = map { $_ => 1 } @$ids;
|
|
if ($add) {
|
|
if ($ids{$id}) {
|
|
@ids = @$ids;
|
|
}
|
|
else {
|
|
@ids = ($id, @$ids);
|
|
|
|
my $hits = scalar @ids;
|
|
if ($type eq 'article' and $hits > 4) {
|
|
pop @ids;
|
|
}
|
|
elsif ($type ne 'article' and $hits > 2) {
|
|
pop @ids;
|
|
}
|
|
$changed = 1;
|
|
}
|
|
}
|
|
elsif ($ids{$id}) {
|
|
@ids = map $_, grep { $_ != $id } @$ids;
|
|
$changed = 1;
|
|
}
|
|
|
|
return unless $changed;
|
|
|
|
$CFG->{$name} = \@ids;
|
|
$CFG->save;
|
|
return;
|
|
}
|
|
|
|
sub is_featured {
|
|
my ($type, $id) = @_;
|
|
|
|
return unless $id and $type;
|
|
return if $type !~ /^(article|photo|video)$/i;
|
|
|
|
my $name = $type eq 'article' ? 'featured_articles' : 'featured_photos';
|
|
my $ids = $CFG->{$name} || [];
|
|
my %ids = map { $_ => 1 } @$ids;
|
|
return $ids{$id} ? 1 : 0;
|
|
}
|
|
|
|
sub fetch_categories {
|
|
my $ids = shift;
|
|
|
|
$ids = ref $ids ? @$ids : [$ids] if $ids;
|
|
|
|
my $tab = $DB->table('Category');
|
|
$tab->select_options('ORDER BY Name');
|
|
my $cond = GT::SQL::Condition->new( CatDepth => '=' => 0);
|
|
$cond->add(ID => '=' => $ids) if $ids;
|
|
|
|
my $cats = $tab->select($cond)->fetchall_hashref;
|
|
foreach (@$cats) {
|
|
$_->{URL} = "$CFG->{build_root_url}/" . $tab->as_url($_->{Full_Name}) . "/" . ($CFG->{build_index_include} ? $CFG->{build_index} : '');
|
|
}
|
|
return $cats;
|
|
}
|
|
|
|
sub fetch_links {
|
|
my %args = @_;
|
|
|
|
return unless %args;
|
|
|
|
my $maxhits = $args{max_hits} || 1;
|
|
my $cond = new GT::SQL::Condition;
|
|
my $url = $CFG->{build_detail_url};
|
|
my (@ids, %paging);
|
|
|
|
my $tab_cat = $DB->table('Category');
|
|
my $tab_lnks = $DB->table('Links');
|
|
my $tab_catlnks = $DB->table(qw/Links CatLinks Category/);
|
|
if ($args{type}) {
|
|
$cond->add(Type => '=' => $args{type});
|
|
$tab_catlnks->select_options("GROUP BY LinkID", "ORDER BY Add_Date DESC", "LIMIT $maxhits");
|
|
}
|
|
elsif ($args{ids}) {
|
|
if (ref $args{ids} eq 'ARRAY') {
|
|
@ids = @{$args{ids}};
|
|
}
|
|
else {
|
|
@ids = split(/\,|\r?\n/, $args{ids});
|
|
}
|
|
return unless scalar @ids;
|
|
|
|
$cond->add(LinkID => '=' => \@ids);
|
|
$tab_catlnks->select_options("ORDER BY Add_Date DESC");
|
|
$tab_catlnks->select_options("LIMIT $maxhits") if $args{max_hits};
|
|
}
|
|
elsif ($args{category}) {
|
|
my $category = $tab_cat->get($args{category});
|
|
return unless $category;
|
|
|
|
$cond->add(Full_Name => 'like' => $category->{Full_Name} . '%');
|
|
$tab_catlnks->select_options("ORDER BY Add_Date DESC", "LIMIT $maxhits");
|
|
}
|
|
elsif ($args{tag} and $args{tag} =~ /^(?:swim|bike|run)$/i) {
|
|
my $vars = GT::Template->vars;
|
|
my $tag = lc $args{tag};
|
|
$url .= "/$tag";
|
|
|
|
$paging{max_hits} = $args{max_hits} || 25;
|
|
$paging{current_page} = $vars->{nh} || 1;
|
|
$paging{page} = $args{url} || ($tag . '/');
|
|
|
|
my $offset = $paging{current_page} == 1 ? 0 : ($paging{current_page} - 1) * $paging{max_hits};
|
|
|
|
$cond->add('tag_' . $tag => '=' => 1);
|
|
$tab_catlnks->select_options("GROUP BY LinkID", "ORDER BY Add_Date DESC", "LIMIT $paging{max_hits} OFFSET $offset");
|
|
}
|
|
elsif ($args{link_type} and $args{link_type} =~ /^(?:photo|video)$/i) {
|
|
my $vars = GT::Template->vars;
|
|
$url .= "/" . ($args{link_type} eq 'video' ? 'Videos' : 'Photos');
|
|
|
|
$paging{max_hits} = $args{max_hits} || 25;
|
|
$paging{current_page} = $vars->{nh} || 1;
|
|
$paging{page} = ($args{link_type} eq 'video' ? 'Videos' : 'Photos') . '/';
|
|
|
|
my $offset = $paging{current_page} == 1 ? 0 : ($paging{current_page} - 1) * $paging{max_hits};
|
|
|
|
$cond->add(Link_Type => '=' => $args{link_type});
|
|
$tab_catlnks->select_options("GROUP BY LinkID", "ORDER BY Add_Date DESC", "LIMIT $paging{max_hits} OFFSET $offset");
|
|
}
|
|
else {
|
|
$tab_catlnks->select_options("GROUP BY LinkID", "ORDER BY Add_Date DESC", "LIMIT $maxhits");
|
|
}
|
|
|
|
my $links = ($tab_catlnks->select(qw/Links.* Name Full_Name/, $cond) or die $GT::SQL::error)->fetchall_hashref;
|
|
return unless scalar @$links;
|
|
|
|
foreach my $l (@$links) {
|
|
$l->{detailed_url} = "$url/" . $tab_lnks->detailed_url($l->{ID}) if $CFG->{build_detailed};
|
|
$l->{URL} = "$CFG->{build_root_url}/" . $tab_cat->as_url($l->{Full_Name}) . "/" . ($CFG->{build_index_include} ? $CFG->{build_index} : '');
|
|
$l->{thumbnail_url} = fetch_thumbnail($l);
|
|
}
|
|
|
|
if (scalar @ids and !$args{db}) {
|
|
my @links_output;
|
|
my %links = map { $_->{ID} => $_ } @$links;
|
|
|
|
foreach my $id (@ids) {
|
|
push @links_output, $links{$id} if $links{$id};
|
|
}
|
|
|
|
return \@links_output;
|
|
}
|
|
elsif (
|
|
($args{link_type} and $args{link_type} =~ /^(?:photo|video)$/) or
|
|
($args{tag} and $args{tag} =~ /^(?:swim|bike|run)$/)
|
|
) {
|
|
$paging{num_hits} = $tab_lnks->select('COUNT(*)', $cond)->fetchrow;
|
|
|
|
my @features;
|
|
if ($paging{current_page} == 1) {
|
|
@features = splice @$links, 0, 3;
|
|
}
|
|
return { loop => $links, features => \@features, paging => \%paging };
|
|
}
|
|
else {
|
|
return $links;
|
|
}
|
|
}
|
|
|
|
sub fetch_category {
|
|
my $catid = shift || return;
|
|
return $DB->table('Category')->get($catid);
|
|
}
|
|
|
|
sub fetch_widget {
|
|
my $id = shift || return;
|
|
|
|
my $tab = $DB->table('Widgets');
|
|
my $widget = $tab->get($id);
|
|
|
|
return unless $widget;
|
|
|
|
if ($widget->{Image}) {
|
|
my $fh = $tab->file_info('Image', $widget->{ID});
|
|
$widget->{Image_URL} = '/images/widgets/' . $fh->File_RelativeURL;
|
|
}
|
|
return $widget;
|
|
}
|
|
|
|
sub fetch_widgets {
|
|
my ($page, $catid) = @_;
|
|
|
|
return unless $page;
|
|
|
|
my $tab_pgwidgets = $DB->table(qw/Widgets PageWidgets/);
|
|
$tab_pgwidgets->select_options('ORDER BY Sort_Pos');
|
|
|
|
my $widgets = [];
|
|
if ($catid =~ /^\d+$/) {
|
|
$widgets = $tab_pgwidgets->select(qw/Widgets.* Sort_Pos/, { Page => $catid })->fetchall_hashref;
|
|
}
|
|
|
|
unless (scalar @$widgets) {
|
|
$widgets = $tab_pgwidgets->select(qw/Widgets.* Sort_Pos/, { Page => $page })->fetchall_hashref;
|
|
}
|
|
my $tab = $DB->table('Widgets');
|
|
foreach my $w (@$widgets) {
|
|
next unless $w->{Image};
|
|
my $fh = $tab->file_info('Image', $w->{ID});
|
|
next unless $fh;
|
|
$w->{Image_URL} = '/images/widgets/' . $fh->File_RelativeURL;
|
|
}
|
|
return $widgets;
|
|
}
|
|
|
|
sub generate_widget {
|
|
my $id = shift || return;
|
|
|
|
my $widget = fetch_widget($id);
|
|
|
|
return unless $widget;
|
|
return Links::SiteHTML::display('include_single_widget', $widget);
|
|
}
|
|
|
|
sub friendly_date {
|
|
my ($date, $timestmp, $format) = @_;
|
|
|
|
return unless $date;
|
|
|
|
my $days = GT::Date::date_diff(GT::Date::date_get(time, '%yyyy%-%mm%-%dd%'), $date);
|
|
unless ($days) {
|
|
my $time = GT::Date::timelocal(GT::Date::parse_format($timestmp, "%yyyy%-%mm%-%dd% %HH%:%MM%:%ss%"));
|
|
my $secs = time - $time;
|
|
return unless $secs;
|
|
|
|
$date = $timestmp;
|
|
return "$secs seconds ago" if $secs < 60;
|
|
|
|
my $mins = int($secs / 60);
|
|
return "$mins minutes ago" if $mins < 60;
|
|
|
|
my $hours = int($secs / 3600);
|
|
return $hours . ($hours > 1 ? " hours ago" : " hour ago");
|
|
}
|
|
else {
|
|
my $time = GT::Date::timelocal(GT::Date::parse_format($date, "%yyyy%-%mm%-%dd%"));
|
|
$date = $time;
|
|
|
|
return ($format or $days > 7)
|
|
? GT::Date::date_get($date, $format || "%mmm% %dd%, %yyyy%")
|
|
: $days . ($days > 1 ? " days ago" : " day ago");
|
|
}
|
|
}
|
|
|
|
sub retrieve_param {
|
|
my ($field, $count) = @_;
|
|
|
|
return unless $field;
|
|
|
|
$count ||= 1;
|
|
my $vars = GT::Template->vars;
|
|
|
|
if ($field eq 'Image_description') {
|
|
return $vars->{"Image${count}_description"};
|
|
}
|
|
elsif ($field =~ /^Image_(.*)$/) {
|
|
return $vars->{"Image${count}_$1"} || $vars->{"Image${count}_path"};
|
|
}
|
|
else {
|
|
return $vars->{"$field$count"};
|
|
}
|
|
}
|
|
|
|
sub fetch_thumbnail {
|
|
my $link = shift || return;
|
|
|
|
if ($link->{Link_Type} eq VIDEO) {
|
|
if ($link->{Thumbnail_URL} and $link->{Thumbnail_URL} ne 'http://') {
|
|
return { small => $link->{Thumbnail_URL} };
|
|
}
|
|
else {
|
|
my $field = Plugins::ConvertVideo::get_file_path($link->{ID}, "thumbnail_file_field");
|
|
return $field->{thumbnail_file_field_path}
|
|
? {
|
|
small => $field->{thumbnail_file_field_path},
|
|
medium => $field->{thumbnail_file_field_path},
|
|
large => $field->{thumbnail_file_field_path},
|
|
largest => $field->{thumbnail_file_field_path},
|
|
}
|
|
: undef;
|
|
}
|
|
}
|
|
else {
|
|
my $slideshow = Plugins::SlideShow::generate_paths($link->{ID});
|
|
if ($slideshow and $slideshow->{image_loop}) {
|
|
return {
|
|
small => $slideshow->{image_loop}->[0]{_thumbnail_path},
|
|
medium => $slideshow->{image_loop}->[0]{_medium_path},
|
|
large => $slideshow->{image_loop}->[0]{_large_path},
|
|
largest => $slideshow->{image_loop}->[0]{_largest_path}
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
sub slideshow_url {
|
|
my $url = shift || return;
|
|
|
|
$url =~ s,^$CFG->{build_detail_url},$CFG->{build_detail_url}/Photos,;
|
|
return $url;
|
|
}
|
|
|
|
sub rewrite_breadcrumbs {
|
|
my ($title_loop, $mode) = @_;
|
|
|
|
return unless ref $title_loop;
|
|
|
|
my @loop;
|
|
foreach my $i (0 .. scalar @$title_loop - 1) {
|
|
my $item = $title_loop->[$i];
|
|
if ($i == 1) {
|
|
if ($item->{Name} =~ /rd\s*aids/i) {
|
|
push @loop, {
|
|
Name => "Races",
|
|
URL => "$CFG->{build_root_url}/Races/index.html"
|
|
};
|
|
}
|
|
elsif ($mode) {
|
|
push @loop, {
|
|
Name => $mode eq 'photo' ? 'Photo Galleries' : 'Videos',
|
|
URL => "$CFG->{build_root_url}/" . ($mode eq 'photo' ? 'Photos' : 'Videos') . "/index.html"
|
|
};
|
|
}
|
|
elsif ($item->{Name} !~ /home|bike\s*fit|products|races|articles|photos|videos|coaching|podcast|privacy|about|agreement/i) {
|
|
push @loop, {
|
|
Name => "Articles",
|
|
URL => "$CFG->{build_root_url}/Articles/index.html"
|
|
};
|
|
}
|
|
}
|
|
push @loop, $item;
|
|
}
|
|
return \@loop;
|
|
}
|
|
|
|
sub build_category {
|
|
my $opts = shift;
|
|
$opts->{id} ||= $IN->param('ID');
|
|
|
|
return @_ unless $opts->{id};
|
|
|
|
my $cfg = Links::Plugins->get_plugin_user_cfg('UI');
|
|
return @_ unless $cfg and $cfg->{merge_categories};
|
|
|
|
my %ids = map { $_ => 1 } split(/\s*,\s*/, $cfg->{merge_categories});
|
|
return @_ unless $ids{$opts->{id}};
|
|
|
|
GT::Plugins->action( STOP );
|
|
|
|
my $cat_db = $DB->table('Category');
|
|
my $link_db = $DB->table('Links');
|
|
my $catlink_db = $DB->table('Links', 'CatLinks');
|
|
my $related_db = $DB->table('CatRelations');
|
|
$Links::Build::GRAND_TOTAL ||= Links::Build::_grand_total();
|
|
|
|
if (ref $opts ne 'HASH') {
|
|
Links::debug("Invalid argument passed to build_category: $opts") if $Links::DEBUG;
|
|
return @_;
|
|
}
|
|
|
|
# Load our category info.
|
|
my $category;
|
|
if ($opts->{id}) {
|
|
$category = $cat_db->get($opts->{id}, 'HASH');
|
|
if (! $category) {
|
|
Links::debug("Invalid category id passed to build_category: $opts->{id}") if $Links::DEBUG;
|
|
return;
|
|
}
|
|
}
|
|
|
|
# Get our options.
|
|
$opts->{mh} = exists $opts->{mh} ? $opts->{mh} : $CFG->{build_span_pages} ? $CFG->{build_links_per_page} : 5000;
|
|
$opts->{nh} = exists $opts->{nh} ? $opts->{nh} : 1;
|
|
$opts->{sb} = exists $opts->{sb} ? $opts->{sb} : $CFG->{build_sort_order_category};
|
|
$opts->{so} = exists $opts->{so} ? $opts->{so} : '';
|
|
if ($opts->{sb} =~ /\b(?:asc|desc)\b/i) {
|
|
$opts->{so} = '';
|
|
}
|
|
$opts->{cat_sb} = exists $opts->{cat_sb} ? $opts->{cat_sb} : $CFG->{build_category_sort};
|
|
$opts->{cat_so} = exists $opts->{cat_so} ? $opts->{cat_so} : '';
|
|
if ($opts->{cat_sb} =~ /\b(?:asc|desc)\b/i) {
|
|
$opts->{cat_so} = '';
|
|
}
|
|
|
|
# Figure out the template set to use.
|
|
$category->{Category_Template} ||= $cat_db->template_set($category->{ID});
|
|
|
|
# Get our output vars.
|
|
my %tplvars = (
|
|
%$category,
|
|
category_id => $category->{ID},
|
|
category_name => $category->{Full_Name},
|
|
header => $category->{Header},
|
|
footer => $category->{Footer},
|
|
meta_name => $category->{Meta_Description},
|
|
meta_keywords => $category->{Meta_Keywords},
|
|
description => $category->{Description},
|
|
random => int rand 10000,
|
|
random1 => int rand 10000,
|
|
random2 => int rand 10000,
|
|
random3 => int rand 10000
|
|
);
|
|
|
|
# Clean up the name.
|
|
my $clean_name = $cat_db->as_url($category->{Full_Name});
|
|
my $build_title = $category->{Full_Name};
|
|
$build_title .= '/' . Links::language('LINKS_PAGE', $opts->{nh}) if $opts->{nh} and $opts->{nh} > 1;
|
|
|
|
$tplvars{title_loop} = Links::Build::build('title', $build_title);
|
|
$tplvars{title_linked} = sub { Links::Build::build('title_linked', $build_title) };
|
|
$tplvars{title} = sub { Links::Build::build('title_unlinked', $build_title) };
|
|
|
|
$tplvars{category_name_escaped} = GT::CGI->escape($category->{Full_Name});
|
|
$tplvars{category_clean} = $tplvars{title};
|
|
($tplvars{category_short}) = $tplvars{category_name} =~ m|([^/]+)$|;
|
|
|
|
# CUSTOMIZED: show all links in a category as well as subcategories
|
|
my $categories = $cat_db->children($category->{ID});
|
|
push @$categories, $category->{ID};
|
|
|
|
my $cond = GT::SQL::Condition->new(
|
|
CategoryID => '=' => $categories,
|
|
isValidated => '=' => 'Yes'
|
|
);
|
|
|
|
# "Optional" payment categories are a hassle, as we have to do two selects,
|
|
# then balance out the mh/nh variables between the two.
|
|
my ($optional_sth, $sth);
|
|
my @select_options;
|
|
push @select_options, "ORDER BY $opts->{sb} $opts->{so}" if $opts->{sb};
|
|
|
|
# Load payment info if payment is enabled. Change sort order by paid links
|
|
# first then free links if payment for this category is optional. If payment
|
|
# is required, we need to remove unpaid links
|
|
if ($CFG->{payment}->{enabled}) {
|
|
require Links::Payment;
|
|
my $payment_info = Links::Payment::cat_payment_info($opts->{id});
|
|
|
|
if ($payment_info->{mode} == OPTIONAL and $CFG->{build_sort_paid_first}) {
|
|
my $paycond = GT::SQL::Condition->new($cond);
|
|
$paycond->add(ExpiryDate => '>=' => time, ExpiryDate => '<=' => UNLIMITED);
|
|
|
|
my $offset = ($opts->{nh} - 1) * $opts->{mh};
|
|
$catlink_db->select_options(@select_options);
|
|
$catlink_db->select_options("LIMIT $opts->{mh} OFFSET $offset");
|
|
$optional_sth = $catlink_db->select('Links.*', $paycond);
|
|
|
|
$cond->add(ExpiryDate => '=' => FREE);
|
|
}
|
|
else {
|
|
# 1) This is an else (instead of elsif ($payment_info->{mode} == REQUIRED)) because the
|
|
# run-time count updating code cannot efficiently take category settings into account
|
|
# as doing so requires either subselects (which older MySQL doesn't support), or a fair
|
|
# bit of Perl code; a single fast count to determine whether the check is necessary
|
|
# won't work. The end result is that counts would be off.
|
|
# 2) Even if this was an elsif, we can't include ExpiryDate <= UNLIMITED (to exclude
|
|
# free links) because links being free is the default for imported, upgraded, and
|
|
# admin-added links, which we don't want to exclude from REQUIRED categories.
|
|
$cond->add(ExpiryDate => '>=' => time);
|
|
}
|
|
}
|
|
|
|
my @results;
|
|
my ($paid_hits, $paid_rows, $offset, $max_hits) = (0, 0, ($opts->{nh} - 1) * $opts->{mh}, $opts->{mh});
|
|
if ($optional_sth) {
|
|
push @results, @{$optional_sth->fetchall_hashref};
|
|
$paid_rows = $optional_sth->rows;
|
|
$paid_hits = $catlink_db->hits;
|
|
if ($paid_rows == $opts->{mh}) {
|
|
$offset = $max_hits = 0;
|
|
}
|
|
elsif ($paid_rows > 0) {
|
|
$offset = 0;
|
|
$max_hits = $opts->{mh} - $paid_rows;
|
|
}
|
|
else {
|
|
$offset -= $paid_hits;
|
|
}
|
|
}
|
|
my $hits;
|
|
# Select links from required categories, not-accepted categories, and optional
|
|
# categories whose paid hits haven't filled the page
|
|
if ($max_hits) { # $max_hits will be 0 when mh paid links are already listed
|
|
$catlink_db->select_options(@select_options);
|
|
$catlink_db->select_options("LIMIT $max_hits OFFSET $offset");
|
|
my @ids = map $_->[0], @{$catlink_db->select('DISTINCT LinkID', $cond)->fetchall_arrayref};
|
|
|
|
$link_db->select_options(@select_options);
|
|
my $sth = $link_db->select({ ID => \@ids });
|
|
|
|
push @results, @{$sth->fetchall_hashref};
|
|
$hits = $catlink_db->hits;
|
|
}
|
|
else {
|
|
$hits = $catlink_db->count($cond);
|
|
}
|
|
|
|
my $numlinks = $tplvars{total} = $hits + $paid_hits;
|
|
$tplvars{total_optional_paid} = $paid_hits;
|
|
|
|
# Get the links.
|
|
$link_db->add_reviews(\@results);
|
|
my @links_loop = map Links::SiteHTML::tags('link', $_, undef) => @results;
|
|
$tplvars{links_loop} = \@links_loop;
|
|
$tplvars{links_count} = @links_loop;
|
|
my $links;
|
|
$tplvars{links} = sub {
|
|
return $links if defined $links;
|
|
$links = '';
|
|
for my $link (@results) {
|
|
$link->{Category_Template} = $category->{Category_Template} if $category->{Category_Template};
|
|
$links .= Links::SiteHTML::display('link', $link);
|
|
}
|
|
return $links;
|
|
};
|
|
# Get the subcategories and related categories as either Yahoo style (integrated) or
|
|
# separated into two outputs..
|
|
my @cat_loop;
|
|
$tplvars{category_loop} = \@cat_loop;
|
|
if ($CFG->{build_category_yahoo}) {
|
|
my @subcat_ids = $cat_db->select(ID => { FatherID => $category->{ID} })->fetchall_list;
|
|
my %related_ids = $related_db->select(qw/RelatedID RelationName/ => { CategoryID => $category->{ID} })->fetchall_list;
|
|
if (@subcat_ids or keys %related_ids) {
|
|
$cat_db->select_options("ORDER BY $opts->{cat_sb} $opts->{cat_so}") if $opts->{cat_sb};
|
|
my $sth = $cat_db->select({ ID => [@subcat_ids, keys %related_ids] });
|
|
my @rel_loop;
|
|
while (my $cat = $sth->fetchrow_hashref) {
|
|
$cat->{URL} = "$CFG->{build_root_url}/" . $cat_db->as_url($cat->{Full_Name}) . "/" . ($CFG->{build_index_include} ? $CFG->{build_index} : '');
|
|
$cat->{RelationName} = '';
|
|
if (exists $related_ids{$cat->{ID}}) {
|
|
$cat->{Related} = 1;
|
|
$cat->{RelationName} = $related_ids{$cat->{ID}};
|
|
# Relations with a custom name need to be re-sorted
|
|
if ($cat->{RelationName}) {
|
|
push @rel_loop, $cat;
|
|
next;
|
|
}
|
|
}
|
|
push @cat_loop, $cat;
|
|
}
|
|
# Re-sort related categories using their RelationName rather than the related
|
|
# category's name
|
|
RELATION: while (my $cat = pop @rel_loop) {
|
|
for (my $i = 0; $i < @cat_loop; $i++) {
|
|
my $name = $cat_loop[$i]->{RelationName} ? $cat_loop[$i]->{RelationName} : $cat_loop[$i]->{Name};
|
|
if (lc $cat->{RelationName} lt lc $name) {
|
|
splice @cat_loop, $i, 0, $cat;
|
|
next RELATION;
|
|
}
|
|
}
|
|
push @cat_loop, $cat;
|
|
}
|
|
my $print_cat;
|
|
$tplvars{category} = sub {
|
|
return $print_cat if defined $print_cat;
|
|
return $print_cat = Links::SiteHTML::display('print_cat', [$category, @cat_loop]);
|
|
};
|
|
}
|
|
else {
|
|
$tplvars{category} = '';
|
|
}
|
|
}
|
|
else {
|
|
# Separate the output.
|
|
$cat_db->select_options("ORDER BY $opts->{cat_sb} $opts->{cat_so}") if $opts->{cat_sb};
|
|
$sth = $cat_db->select({ FatherID => $category->{ID} });
|
|
while (my $cat = $sth->fetchrow_hashref) {
|
|
$cat->{URL} = "$CFG->{build_root_url}/" . $cat_db->as_url($cat->{Full_Name}) . "/" . ($CFG->{build_index_include} ? $CFG->{build_index} : '');
|
|
push @cat_loop, $cat;
|
|
}
|
|
if (@cat_loop) {
|
|
my $print_cat;
|
|
$tplvars{category} = sub {
|
|
return $print_cat if defined $print_cat;
|
|
return $print_cat = Links::SiteHTML::display('print_cat', [$category, @cat_loop]);
|
|
};
|
|
}
|
|
else {
|
|
$tplvars{category} = '';
|
|
}
|
|
$tplvars{related} = '';
|
|
$tplvars{related_loop} = [];
|
|
|
|
my %related_ids = $related_db->select(qw/RelatedID RelationName/ => { CategoryID => $category->{ID} })->fetchall_list;
|
|
if (keys %related_ids) {
|
|
$cat_db->select_options("ORDER BY $opts->{cat_sb} $opts->{cat_so}") if $opts->{cat_sb};
|
|
my $sth = $cat_db->select({ ID => [keys %related_ids] });
|
|
while (my $cat = $sth->fetchrow_hashref) {
|
|
my $url = $CFG->{build_root_url} . "/" . $cat_db->as_url($cat->{Full_Name}) . "/" . ($CFG->{build_index_include} ? $CFG->{build_index} : '');
|
|
$cat->{URL} = $url;
|
|
$cat->{RelationName} = $related_ids{$cat->{ID}};
|
|
push @{$tplvars{related_loop}}, $cat;
|
|
$tplvars{related} .= qq|<li><a href="$url">| . ($related_ids{$cat->{ID}} || $cat->{Full_Name}) . "</a></li>";
|
|
}
|
|
}
|
|
}
|
|
|
|
# Plugins can use the build_category_loop hook to change the category
|
|
# results before they are returned to the template.
|
|
$PLG->dispatch(build_category_loop => sub { } => \@cat_loop);
|
|
|
|
# Get the header and footer from file if it exists, otherwise assume it is html.
|
|
if ($tplvars{header} and $tplvars{header} =~ /^\S{1,20}$/ and -e "$CFG->{admin_root_path}/headers/$tplvars{header}") {
|
|
local (@ARGV, $/) = "$CFG->{admin_root_path}/headers/$tplvars{header}";
|
|
$tplvars{header} = <>;
|
|
}
|
|
if ($tplvars{footer} and $tplvars{footer} =~ /^\S{1,20}$/ and -e "$CFG->{admin_root_path}/footers/$tplvars{footer}") {
|
|
local (@ARGV, $/) = "$CFG->{admin_root_path}/footers/$tplvars{footer}";
|
|
$tplvars{footer} = <>;
|
|
}
|
|
|
|
# If we are spanning pages, figure out toolbars and such.
|
|
if ($CFG->{build_span_pages}) {
|
|
my $lpp = $CFG->{build_links_per_page};
|
|
my $nh = $opts->{nh};
|
|
my $url = $CFG->{build_root_url} . "/" . $clean_name;
|
|
$tplvars{next} = $tplvars{prev} = "";
|
|
if ($numlinks > ($nh * $lpp)) {
|
|
$tplvars{next} = "$url/$CFG->{build_more}" . ($nh + 1) . "$CFG->{build_extension}";
|
|
}
|
|
if ($nh == 2) {
|
|
$tplvars{prev} = "$url/" . ($CFG->{build_index_include} ? $CFG->{build_index} : '');
|
|
}
|
|
elsif ($nh > 2) {
|
|
$tplvars{prev} = "$url/$CFG->{build_more}" . ($nh - 1) . "$CFG->{build_extension}";
|
|
}
|
|
if ($tplvars{next} or $tplvars{prev}) {
|
|
$tplvars{next_span} = Links::Build::build('toolbar', { url => $url, numlinks => $numlinks, nh => $nh });
|
|
$tplvars{paging} = {
|
|
page => "$clean_name/",
|
|
page_format => 1,
|
|
num_hits => $numlinks,
|
|
max_hits => $opts->{mh},
|
|
current_page => $opts->{nh}
|
|
};
|
|
}
|
|
}
|
|
|
|
return Links::SiteHTML::display('category', \%tplvars);
|
|
}
|
|
|
|
sub fetch_widget_external_links {
|
|
my $id = shift || return;
|
|
|
|
return $DB->table('WidgetLinks')->select({ WidgetID => $id })->fetchall_hashref;
|
|
}
|
|
1;
|