# ==================================================================
# Gossamer Links - enhanced directory management system
#
#   Website  : http://gossamer-threads.com/
#   Support  : http://gossamer-threads.com/scripts/support/
#   CVS Info : 087,071,086,086,085      
#   Revision : $Id: Page.pm,v 1.33 2007/12/19 06:59:12 brewt Exp $
#
# Copyright (c) 2001 Gossamer Threads Inc.  All Rights Reserved.
# Redistribution in part or in whole strictly prohibited. Please
# see LICENSE file for full details.
# ==================================================================

package Links::User::Page;
# ==================================================================
use strict;
use Links qw/:objects/;
use Links::Build;
use Links::SiteHTML;

sub handle {
# --------------------------------------------------------------
# Wrap in a subroutine to prevent possible mod_perl probs.
#
    $ENV{PATH_INFO} and ($ENV{PATH_INFO} =~ s/.*page\.cgi//);
    my $page = $IN->param('g') || $ENV{PATH_INFO} || '';

# We can display a custom template by passing in p=template (the p is for
# page).
    my $custom = $IN->param('p') || '';
    return generate_custom_page($custom) if $custom;

# Clean up page a little.
    $page =~ s|^/+||;
    $page =~ s|/+$||;

# Reset the grand total.
    $Links::Build::GRAND_TOTAL = 0;

# Figure out what to look for.
    my ($new_match)  = $CFG->{build_new_url}     =~ m{^\Q$CFG->{build_root_url}\E/(.+)};
    my ($cool_match) = $CFG->{build_cool_url}    =~ m{^\Q$CFG->{build_root_url}\E/(.+)};
    my ($rate_match) = $CFG->{build_ratings_url} =~ m{^\Q$CFG->{build_root_url}\E/(.+)};

# Strip out the index.html/more*.html if it is there.
    $page =~ s{/*(?:\Q$CFG->{build_home}\E|\Q$CFG->{build_index}\E|\Q$CFG->{build_more}\E\d+\Q$CFG->{build_extension}\E)$}{};

    if ($new_match and $page =~ m{^\Q$new_match\E(?:/|$)}) {
        $PLG->dispatch('generate_new', \&generate_new_page);
    }
    elsif ($cool_match and $page =~ m{^\Q$cool_match\E(?:/|$)}) {
        $PLG->dispatch('generate_cool', \&generate_cool_page);
    }
    elsif ($rate_match and $page =~ m{^\Q$rate_match\E/?$}) {
        $PLG->dispatch('generate_rate', \&generate_rate_page);
    }
# By default the detailed page format in dynamic mode will be
# "<%config.build_detailed_url%>/<%ID%>.<%build_extension%>", but other certain
# formats can be used without breaking other URLs.
    elsif ($page =~ /\d+\Q$CFG->{build_extension}\E$/) {
        $PLG->dispatch('generate_detailed', \&generate_detailed_page);
    }
    elsif ($page !~ /\S/) {
        $PLG->dispatch('generate_home', \&generate_home_page);
    }
    elsif ($page =~ /(\w+\.cgi)/) {
        print $IN->redirect("$CFG->{db_cgi_url}/$1");
    }
    else {
        $PLG->dispatch('generate_category', \&generate_category_page);
    }
}

sub generate_custom_page {
# --------------------------------------------------------
# Displays a custom template.
#
    my $page = shift;
    if ($CFG->{dynamic_404_status}) {
        my $template_set = Links::template_set();
        if (! Links::template_exists($template_set, "$page.html")) {
            print "Status: 404" . $GT::CGI::EOL;
        }
    }
    print $IN->header();
    print Links::SiteHTML::display($page, {});
}

sub generate_home_page {
# --------------------------------------------------------
# Display the home page.
#
    print $IN->header();
    print Links::Build::build(home => {});
}

sub generate_category_page {
# --------------------------------------------------------
# This routine will display a category, first thing we need
# to do is figure out what category we've been asked for.
#
    my $page_num = 1;
    my $page = $IN->param('g') || $ENV{PATH_INFO} || '';
    $page_num = $1 if $page =~ s{/\Q$CFG->{build_more}\E(\d+)\Q$CFG->{build_extension}\E$}{};
    $page =~ s/\Q$CFG->{build_index}\E$//;
    $page =~ s|^/+||;
    $page =~ s|/+$||;
    my $like = $page;
    $page =~ y/_/ /;

# Now we get the ID number of the category based on the URL.
    my $cat_db = $DB->table('Category');
    my $id;
    if ($CFG->{build_category_dynamic} eq 'ID' or $page =~ /^\d+$/) {
        ($id) = $page =~ /(\d+)$/;
# Make sure the ID is valid
        $id = $cat_db->select(ID => { ID => $id })->fetchrow;
    }
    else {
        $id = $cat_db->select(ID => { ($CFG->{build_category_dynamic} || 'Full_Name') => $page })->fetchrow;
    }

    if (!$id) {
# Oops, we may have had a escaped character '_' that wasn't a space. We need
# to look it up manually.
        $like =~ y/'"//d;
        $id = $cat_db->select(ID => GT::SQL::Condition->new(($CFG->{build_category_dynamic} || 'Full_Name') => LIKE => $like))->fetchrow;
    }

# Check for valid sort order.
    my %opts;
    $opts{id} = $id;
    $opts{nh} = $page_num;
    $opts{sb} = $IN->param('sb');
    $opts{so} = $IN->param('so');
    $opts{cat_sb} = $IN->param('cat_sb');
    $opts{cat_so} = $IN->param('cat_so');
    unless ($opts{sb} and exists $DB->table('Links')->cols->{$opts{sb}} and (not $opts{so} or $opts{so} =~ /^(?:desc|asc)$/i)) {
        delete $opts{sb};
        delete $opts{so};
    }
    unless ($opts{cat_sb} and exists $DB->table('Category')->cols->{$opts{cat_sb}} and (not $opts{cat_so} or $opts{cat_so} =~ /^(?:desc|asc)$/i)) {
        delete $opts{cat_sb};
        delete $opts{cat_so};
    }

    if ($id) {
        print $IN->header();
        print Links::Build::build('category', \%opts);
    }
    else {
        print "Status: 404" . $GT::CGI::EOL if $CFG->{dynamic_404_status};
        print $IN->header();
        print Links::SiteHTML::display('error', { error => Links::language('PAGE_INVALIDCAT', $page) });
    }
}

sub generate_new_page {
# --------------------------------------------------------
# Creates a "What's New" page. Set build_span_pages to 1 in setup
# and it will create a seperate page for each date.
#
    my ($page, $date);

    $page = $IN->param('g') || $ENV{PATH_INFO} || '';
    if ($page =~ /\Q$CFG->{build_index}\E$/) {
        $date = '';
    }
    else {
        ($date) = $page =~ m{/([^/]+)\Q$CFG->{build_extension}\E$};
    }

    if ($date) {
        my $nh   = 1;
        my $lpp  = $CFG->{build_links_per_page} || 25;
        if ($date =~ s/_(\d+)//) {
            $nh = $1;
        }
        print $IN->header();
        print Links::Build::build('new_subpage', { date => $date, mh => $lpp, nh => $nh });
    }
    elsif ($CFG->{build_new_date_span_pages}) {
        print $IN->header();
        print Links::Build::build('new_index', {});
    }
    else {
        print $IN->header();
        print Links::Build::build('new', {});
    }
}

sub generate_cool_page {
# --------------------------------------------------------
# Creates a "What's Cool" page.
#
    my $page = $IN->param('g') || $ENV{PATH_INFO} || '';
    my $nh = 1;
    my $mh = $CFG->{build_span_pages} ? $CFG->{build_links_per_page} : 1000;
    if ($page =~ /\Q$CFG->{build_more}\E(\d+)\Q$CFG->{build_extension}\E$/) {
        $nh = $1;
    }
    print $IN->header();
    print Links::Build::build('cool', { mh => $mh, nh => $nh });
}

sub generate_rate_page {
# --------------------------------------------------------
# Creates a Top 10 ratings page.
#
    print $IN->header();
    print Links::Build::build('rating', {});
}

sub generate_detailed_page {
# --------------------------------------------------------
# This routine build a single page for every link.
#
    my ($page, $id, $link, $detail_match);

    $page = $IN->param('g') || $ENV{PATH_INFO} || '';
    ($id) = $page =~ /(\d+)\Q$CFG->{build_extension}\E$/;

# Fetch the category info if the link is in multiple categories and the category
# the detailed page was accessed from was passed in.  This is done so the next
# and previous links are correct.
# Note that due to the URL transformation (Links::clean_output), it isn't
# possible to pass in the CategoryID unless the detailed url is self generated
# (ie. <%detailed_url%> isn't used).
    if ($id) {
        my $cat_id = $IN->param('CategoryID');
        if ($cat_id and $DB->table('CatLinks')->count({ LinkID => $id, CategoryID => $cat_id })) {
            $link = $DB->table(qw/Links CatLinks Category/)->select({ LinkID => $id, CategoryID => $cat_id })->fetchrow_hashref;
        }
        else {
            $link = $DB->table('Links')->get($id, 'HASH');
        }
    }

    if (!$link) {
        print "Status: 404" . $GT::CGI::EOL if $CFG->{dynamic_404_status};
        print $IN->header();
        print Links::SiteHTML::display('error', { error => Links::language('PAGE_INVALIDDETAIL', $page) });
        return;
    }

    print $IN->header();
    print Links::Build::build('detailed', $link);
}

1;
