Links v2 Mod - Multiple Categories

Much of the code for the multiple categories mod is already incorporated into Links v2. I doubt you will have any problems, everything is pretty much straight forward. However, there may be something I overlooked as I originally made these modifications to Links b5. If you do find a problem, let me know and I'll get it corrected asap.

The coolest thing about this mod is the change I made to build_stats. Links v2 will now accurately tabulate the number of links in each category without throwing off the grand_total for the entire database, and/or vice versa. To see the mod in action go to Online-Sweepstakes.com, a work in progress.

I do have a few other mods that I've written and will make them available once I get some time. If anyone can design some excellent graphics for me, I might be willing to trade for Links/cgi customization, recognition, $$$, or a combination. If interested, send an email to webmaster@online-sweepstakes.com.

If you're not comfortable with Perl, you might want to make back up copies of your files before you change anything. The changes are highlighted in bold red. Have fun and good luck!

Brent
"loopy"

Links v2 Comments Field Mod

Online-Sweepstakes.com

In the file "links.def" replace...


# Database Definition: LINKS
# --------------------------------------------------------
# Definition of your database file.
    %db_def = (
            ID              => [0,  'numer',     5,     8,  1,  '',          ''],
            Title           => [1,  'alpha',     40,   75,  1,  '',          ''],
            URL             => [2,  'alpha',     40,   75,  1,  'http://',   '^http|news|mailto|ftp'],
            Date            => [3,  'date',      15,   15,  1,  \&get_date,  ''],
            Category        => [4,  'alpha',      0,  150,  1,  '',          ''],
            Description     => [5,  'alpha', '40x3',  500,  0,  '',          ''],
            'Contact Name'  => [6,  'alpha',     40,   75,  1,  '',          ''],
            'Contact Email' => [7,  'alpha',     40,   75,  1,  '',          '.+@.+\..+'],
            Hits            => [8,  'numer',      10,  10,  1,  '0',         '\d+'],        
            isNew           => [9,  'alpha',      0,    5,  0,  'No',        ''],
            isPopular       => [10, 'alpha',      0,    5,  0,  'No',        ''],
            Rating          => [11, 'numer',      10,  10,  1,  0,           '^[\d\.]+$'],
            Votes           => [12, 'numer',      10,  10,  1,  0,           '^\d+$'],
            ReceiveMail     => [13, 'alpha',      10,  10,  1,  'Yes',       'No|Yes']
    );

 

with...


# Database Definition: LINKS
# --------------------------------------------------------
# Definition of your database file.
    %db_def = (
            ID              => [0,  'numer',     5,     8,  1,  '',          ''],
            Title           => [1,  'alpha',     40,   75,  1,  '',          ''],
            URL             => [2,  'alpha',     40,   75,  1,  'http://',   '^http|news|mailto|ftp'],
            Date            => [3,  'date',      15,   15,  1,  \&get_date,  ''],
            Category        => [4,  'alpha',      0,  150,  1,  '',          ''],
            AltCategories   => [5,  'alpha',      0,  500,  0,  '',          ''],
            Description     => [6,  'alpha', '40x3',  500,  0,  '',          ''],
            'Contact Name'  => [7,  'alpha',     40,   75,  1,  '',          ''],
            'Contact Email' => [8,  'alpha',     40,   75,  1,  '',          '.+@.+\..+'],
            Hits            => [9,  'numer',      10,  10,  1,  '0',         '\d+'],        
            isNew           => [10,  'alpha',      0,    5,  0,  'No',        ''],
            isPopular       => [11, 'alpha',      0,    5,  0,  'No',        ''],
            Rating          => [12, 'numer',      10,  10,  1,  0,           '^[\d\.]+$'],
            Votes           => [13, 'numer',      10,  10,  1,  0,           '^\d+$'],
            ReceiveMail     => [14, 'alpha',      10,  10,  1,  'Yes',       'No|Yes']
    );

 

and replace...


# Field Number of some important fields. The number is from %db_def above
# where the first field equals 0.
	$db_category = 4;     $db_modified = 3;  $db_url = 2; 
	$db_hits = 8;         $db_isnew = 9;     $db_ispop = 10;
	$db_contact_name = 6; $db_contact_email = 7; $db_title = 1;
	$db_votes = 12;       $db_rating = 11;   $db_mail = 13;

 

with...


# Field Number of some important fields. The number is from %db_def above
# where the first field equals 0.
	$db_alt = 5;
        $db_category = 4;      $db_modified = 3;      $db_url = 2; 
	$db_hits = 9;          $db_isnew = 10;        $db_ispop = 11;
	$db_contact_name = 7;  $db_contact_email = 8; $db_title = 1;
	$db_votes = 13;        $db_rating = 12;       $db_mail = 14;

 

and replace...


# Field names you want to allow visitors to search on:
    @search_fields = (1,2,5);

 

with...


# Field names you want to allow visitors to search on:
    @search_fields = (1,2,6); 

 

In the file "nph-build.cgi" replace...


sub build_stats {
# --------------------------------------------------------
# This routine does a lot of the messy work. It builds globally accessible
# arrays of new_links and cool_links. It finds out how many links are in each
# category, and whether a category contains a new/modified link.

    my (@values, $category, $cat, @alt_categories, @categorylist, $depth, $i, $cat);
    my $staggered_mode = shift || undef;

    open (DB, "<$db_file_name") or &cgierr("unable to open database: $db_file_name. Reason: $!");
    LINE: while (<DB>) {
        /^#/      and next LINE;        # Skip comment Lines.
        /^\s*$/   and next LINE;        # Skip blank lines.
        chomp;  
        @values   = &split_decode ($_);     
        $category = $values[$db_category];
        
# Add the link to the list of links.        
        push (@{$links{$category}}, @values) if (!$staggered_mode);
        $grand_total++;

# Add the link to the alternate categories as well.
        if (defined $db_alt) {
            @alt_categories = split(/\Q$db_delim\E/, $values[$db_alt]);
            foreach (@alt_categories) {
                push (@{$links{$_}}, @values);
            }
        }
        
# Add the link to the list of new links if it is new.
        push (@{$new_links{$category}}, @values) if ($values[$db_isnew] eq "Yes");

# Add the link to the list of cool links if it is popular.
        push (@{$cool_links{$category}}, @values) if ($values[$db_ispop] eq "Yes");

# This adds one to the total of each category above the current category.
# We have to caluclate the affect of the link on each alt category as well as the main.
        foreach $cat ($category, @alt_categories) {

# Calculate the stats: the number of links and the newest link.                  
            @categorylist = split (/\//, $cat);
            $depth = $#categorylist;                                

# This adds one to the total of each category above the current category,
# and also marks any above categories new, if this link is new.
            for $i (0 .. $depth) {
                $stats{$cat}[0]++;
                if ((!$stats{$cat}[1]) || &compare_dates($values[$db_modified], $stats{$cat}[1])) {
                    $stats{$cat}[1] = $values[$db_modified];
                }
                pop (@categorylist);
                $cat = join("/", @categorylist);
            }                   
        }
    }   
    close DB;
    
# Now we have to sort the links and categories..
    if (!$staggered_mode) {
        foreach $link ( keys %links ) {
            @{$links{$link}} = &build_sorthit (@{$links{$link}});
        }
        foreach $cat ( keys %subcategories ) {
            @{$subcategories{$cat}} = sort @{$subcategories{$cat}};
        }   
    }
    $grand_total ||= 0;
}   

 

with...


sub build_stats {
# --------------------------------------------------------
# This routine does a lot of the messy work. It builds globally accessible
# arrays of new_links and cool_links. It finds out how many links are in each
# category, and whether a category contains a new/modified link.

	my (@values, $category, $cat, @alt_categories, @categorylist, $depth, $i, $cat, %unique_categories);
	my $staggered_mode = shift || undef;

	open (DB, "<$db_file_name") or &cgierr("unable to open database: $db_file_name. Reason: $!");
	LINE: while (<DB>) {
		/^#/      and next LINE;		# Skip comment Lines.
		/^\s*$/   and next LINE;		# Skip blank lines.
		chomp;	
		@values   = &split_decode ($_);		
		$category = $values[$db_category];
		
# Add the link to the list of links.		
		push (@{$links{$category}}, @values) if (!$staggered_mode);
		$grand_total++;

# Add the link to the alternate categories as well.
		if (defined $db_alt) {
			@alt_categories = split(/\Q$db_delim\E/, $values[$db_alt]);
			foreach (@alt_categories) {
				push (@{$links{$_}}, @values);
			}
		}
		
# Add the link to the list of new links if it is new.
		push (@{$new_links{$category}}, @values) if ($values[$db_isnew] eq "Yes");

# Add the link to the list of cool links if it is popular.
		push (@{$cool_links{$category}}, @values) if ($values[$db_ispop] eq "Yes");

# This adds one to the total of each category above the current category.
# We have to caluclate the affect of the link on each alt category as well as the main.
		%unique_categories = "";
		foreach $cat ($category, @alt_categories) {

# Calculate the stats: the number of links and the newest link.            
			@categorylist = split (/\//, $cat);
			$depth = $#categorylist;

# This adds one to the total of each category above the current category,
# and also marks any above categories new, if this link is new.
			for $i (0 .. $depth) {
				if (! defined ($unique_categories{$cat})) {
					$unique_categories{$cat} += 1;
					$stats{$cat}[0]++;
				}
				if ((!$stats{$cat}[1]) || &compare_dates($values[$db_modified], $stats{$cat}[1])) {
					$stats{$cat}[1] = $values[$db_modified];
				}
				pop (@categorylist);
				$cat = join("/", @categorylist);
			}          			
		}
	}   
	close DB;
	
# Now we have to sort the links and categories..
	if (!$staggered_mode) {
		foreach $link ( keys %links ) {
			@{$links{$link}} = &build_sorthit (@{$links{$link}});
		}
		foreach $cat ( keys %subcategories ) {
			@{$subcategories{$cat}} = sort @{$subcategories{$cat}};
		}	
	}
	$grand_total ||= 0;
}   

 

And finally in the file "db_utils.pl" replace...


sub build_html_record_form {
# --------------------------------------------------------
# Builds a record form based on the config information.
#
	my ($output, $field, $multiple, $name);
	($_[0] eq "multiple") and ($multiple = 1) and shift;
	my (%rec) = @_;
	$output = "<p><table border=1>";
# Go through a little hoops to only load category list when absolutely neccessary.
	if ($in{'db'} eq 'links') {
		exists $db_select_fields{$db_cols[$db_category]}
			or ($db_select_fields{$db_cols[$db_category]} = join (",", &category_list));
	}
	else {
		$db_select_fields{'Related'} or
			($db_select_fields{'Related'} = $db_select_fields{'Mult-Related'} = join ",", &category_list);
	} 
	foreach $field (@db_cols) { 
# Set the field name to field-key if we are doing multiple forms.
		$multiple ? ($name = "$field-$rec{$db_key}") : ($name = $field);
		if ($db_select_fields{"Mult-$field"}) {$output .= "<tr><td align=right valign=top width=20%><$font>$field:</font></td><td width=80%>" . &build_select_field($field, $rec{$field}, $name, "MULTIPLE SIZE=3") . "</td></tr>\n";}
		elsif ($db_select_fields{$field}) {$output .= "<tr><td align=right valign=top width=20%><$font>$field:</font></td><td width=80%>" . &build_select_field($field, $rec{$field}, $name) . "</td></tr>\n";}
		elsif ($db_radio_fields{$field}) {$output .= "<tr><td align=right valign=top width=20%><$font>$field:</font></td><td width=80%>" . &build_radio_field($field, $rec{$field}, $name) . "</td></tr>\n";}
		elsif ($db_checkbox_fields{$field}) {$output .= "<tr><td align=right valign=top width=20%><$font>$field:</font></td><td width=80%>" . &build_checkbox_field ($field, $rec{$field}, $name) . "</td></tr>\n";}
		elsif ($db_form_len{$field} =~ 
				/(\d+)x(\d+)/) {$output .= qq~<tr><td align=right valign=top width=20%><$font>$field:</font></td><td width=80%><textarea wrap="virtual" name="$name" cols="$1" rows="$2">$rec{$field}</textarea></td></tr>\n~;}
		elsif ($db_form_len{$field} == -1) {$output = qq~<input type=hidden name="$field" value="$rec{$field}">\n$output~; }
		else {$output .= qq~<tr><td align=right valign=top width=20%><$font>$field:</font></td><td width=80%><input type=text name="$name" value="$rec{$field}" size="$db_form_len{$field}" maxlength="$db_lengths{$field}"></td></tr>\n~;}
	}
	$output .= "</table></p>\n";
	return $output;
}       

 

with...


sub build_html_record_form {
#--------------------------------------------------------
# Builds a record form based on the config information.
#
	my ($output, $field, $multiple, $name);
	($_[0] eq "multiple") and ($multiple = 1) and shift;
	my (%rec) = @_; 
	$output = "<p><table border=1>";
# Go through a little hoops to only load category list when absolutely neccessary.
	if ($in{'db'} eq 'links') {
		exists $db_select_fields{$db_cols[$db_category]}
			or ($db_select_fields{$db_cols[$db_category]} = join (",", &category_list));
	($db_select_fields{$db_cols[$db_alt]} = $db_select_fields{'Mult-AltCategories'} = join (",", &category_list));
	}
	else {
		$db_select_fields{'Related'} or
			($db_select_fields{'Related'} = $db_select_fields{'Mult-Related'} = join ",", &category_list);
	} 
	foreach $field (@db_cols) { 
# Set the field name to field-key if we are doing multiple forms.
		$multiple ? ($name = "$field-$rec{$db_key}") : ($name = $field);
		if ($db_select_fields{"Mult-$field"}) {$output .= "<tr><td align=right valign=top width=20%><$font>$field:</font></td><td width=80%>" . &build_select_field($field, $rec{$field}, $name, "MULTIPLE SIZE=5") . "</td></tr>\n";}
		elsif ($db_select_fields{$field}) {$output .= "<tr><td align=right valign=top width=20%><$font>$field:</font></td><td width=80%>" . &build_select_field($field, $rec{$field}, $name) . "</td></tr>\n"; }
		elsif ($db_radio_fields{$field}) {$output .= "<tr><td align=right valign=top width=20%><$font>$field:</font></td><td width=80%>" . &build_radio_field($field, $rec{$field}, $name) . "</td></tr>\n"; }
		elsif ($db_checkbox_fields{$field}) {$output .= "<tr><td align=right valign=top width=20%><$font>$field:</font></td><td width=80%>" . &build_checkbox_field ($field, $rec{$field}, $name) . "</td></tr>\n"; }
		elsif ($db_form_len{$field} =~ 
				/(\d+)x(\d+)/) {$output .= qq~<tr><td align=right valign=top width=20%><$font>$field:</font></td><td width=80%><textarea wrap="virtual" name="$name" cols="$1" rows="$2">$rec{$field}</textarea></td></tr>\n~;}
		elsif ($db_form_len{$field} == -1) {$output = qq~<input type=hidden name="$field" value="$rec{$field}">\n$output~; }
		else {$output .= qq~<tr><td align=right valign=top width=20%><$font>$field:</font></td><td width=80%><input type=text name="$name" value="$rec{$field}" size="$db_form_len{$field}" maxlength="$db_lengths{$field}"></td></tr>\n~;}
	}
	$output .= "</table></p>\n";
	return $output;
} 

 

top