IndexPlWalkthroughNotes
index.pl
- !/usr/bin/perl -w
- This code is a part of Slash, and is released under the GPL.
- Copyright 1997-2005 by Open Source Technology Group. See README
- and COPYING for more information, or see http://slashcode.com/.
- $Id$
use strict; use Slash; use Slash::Display; use Slash::Utility; use Slash::XML; use Time::HiRes; use Slash::Slashboxes;
sub main { my $start_time = Time::HiRes::time;
my $constants = getCurrentStatic(); my $user = getCurrentUser(); my $form = getCurrentForm(); my $slashdb = getCurrentDB(); my $reader = getObject('Slash::DB', { db_type => 'reader' });
return if redirect_home_if_necessary();
my($stories, $Stories); # could this be MORE confusing please? kthx
# why is this commented out? -- pudge # $form->{mode} = $user->{mode} = "dynamic" if $ENV{SCRIPT_NAME};
# Handle moving a block up or down, or removing it. if ($form->{bid} && $form->{op} && $form->{op} =~ /^[udx]$/) { if ($form->{op} eq 'u') { upBid($form->{bid}) } elsif ($form->{op} eq 'd') { dnBid($form->{bid}) } else { rmBid($form->{bid}) } redirect($ENV{HTTP_REFERER} || $ENV{SCRIPT_NAME}); return; }
my $rss = $constants->{rss_allow_index} && $form->{content_type} && $form->{content_type} =~ $constants->{feed_types} && ( $user->{is_admin} || ($constants->{rss_allow_index} > 1 && $user->{is_subscriber}) || ($constants->{rss_allow_index} > 2 && !$user->{is_anon}) );
# $form->{logtoken} is only allowed if using rss if ($form->{logtoken} && !$rss) { redirect($ENV{SCRIPT_NAME}); }
my $skin_name = $form->{section}; my $skid = $skin_name ? $reader->getSkidFromName($skin_name) : determineCurrentSkin(); setCurrentSkin($skid); my $gSkin = getCurrentSkin(); $skin_name = $gSkin->{name};
- XXXSKIN I'm turning custom numbers of maxstories off for now, so all
- users get the same number. This will improve query cache hit rates and
- right now we need all the edge we can get. Hopefully we can get this
- back on soon. - Jamie 2004/07/17
- my $user_maxstories = $user->{maxstories};
- my $user_maxstories = getCurrentAnonymousCoward("maxstories");
# Decide what our issue is going to be. my $limit; my $issue = $form->{issue} || ; $issue = if $issue !~ /^\d{8}$/;
- if ($issue) {
- if ($user->{is_anon}) {
- $limit = $gSkin->{artcount_max} * 3;
- } else {
- $limit = $user_maxstories * 7;
- }
- } elsif ($user->{is_anon}) {
- $limit = $gSkin->{artcount_max};
- } else {
- $limit = $user_maxstories;
- }
my $gse_hr = { }; # Set the characteristics that stories can be in to appear. This # is a simple list: the current skin's nexus, and then if the # current skin is the mainpage, add in the list of nexuses that # the mainpage needs the user's story_always_topic # and story_always_nexus tids. # It's pretty ugly that this duplicates some of the effect of # getDispModesForStories(). This code really should be # simplified and consolidated. $gse_hr->{tid} = [ $gSkin->{nexus} ]; if ($gSkin->{skid} == $constants->{mainpage_skid}) { # This may or may not be necessary; gSE() should # already know to do this. But it should not hurt # to add the tids here. if ($constants->{brief_sectional_mainpage}) { my $nexus_children = $reader->getMainpageDisplayableNexuses(); push @{$gse_hr->{tid}}, @$nexus_children; }
my @extra_tids = split ",", $user->{story_always_topic}; push @extra_tids, split ",", $user->{story_always_nexus}; # Let gse know that we're asking for extra tids beyond # those expected by default. if (@extra_tids) { $gse_hr->{tid_extras} = 1; push @{$gse_hr->{tid}}, @extra_tids; }
# Eliminate duplicates and sort. my %tids = ( map { ($_, 1) } @{$gse_hr->{tid}} ); $gse_hr->{tid} = [ keys %tids ]; } @{ $gse_hr->{tid} } = sort { $a <=> $b } @{ $gse_hr->{tid} };
# Now exclude characteristics. One tricky thing here is that # we never exclude the nexus for the current skin -- if the user # went to foo.sitename.com explicitly, then they're going to see # stories about foo, regardless of their prefs. Another tricky # thing is that story_never_topic doesn't get used unless a var # and/or this user's subscriber status are set a particular way. my @never_tids = split /,/, $user->{story_never_nexus}; if ($constants->{story_never_topic_allow} == 2 || ($user->{is_subscriber} && $constants->{story_never_topic_allow} == 1) ) { push @never_tids, split /,/, $user->{story_never_topic}; } @never_tids = grep { /^'?\d+'?$/ && $_ != $gSkin->{nexus} } @never_tids; $gse_hr->{tid_exclude} = [ @never_tids ] if @never_tids; $gse_hr->{uid_exclude} = [ split /,/, $user->{story_never_author} ] if $user->{story_never_author};
- For now, all users get the same number of maxstories.
- $gse_hr->{limit} = $user_maxstories if $user_maxstories;
$gse_hr->{issue} = $issue if $issue; my $gse_db = rand(1) < $constants->{index_gse_backup_prob} ? $reader : $slashdb; $stories = $gse_db->getStoriesEssentials($gse_hr);
# Workaround for a bug in saving/updating. Sometimes a story # will be saved with neverdisplay=1 but with an incorrect # story_topics_rendered row that places it in a nexus as well. # Until we figure out why, there's additional logic here to # make sure we screen out neverdisplay stories. -Jamie 2007-08-06 my $stoid_in_str = join(',', map { $_->{stoid} } @$stories); my $nd_hr = { }; if ($stoid_in_str) { $nd_hr = $gse_db->sqlSelectAllKeyValue('stoid, value', 'story_param', qq{stoid IN ($stoid_in_str) AND name='neverdisplay' AND value != 0}); if (keys %$nd_hr) { for my $story_hr (@$stories) { $story_hr->{neverdisplay} = 1 if $nd_hr->{ $story_hr->{stoid} }; } } } if (grep { $_->{neverdisplay} } @$stories) { require Data::Dumper; $Data::Dumper::Sortkeys = 1; my @nd_ids = map { $_->{stoid} } grep { $_->{neverdisplay} } @$stories; my $gse_str = Data::Dumper::Dumper($gse_hr); $gse_str =~ s/\s+/ /g; print STDERR scalar(gmtime) . " index.pl ND story '@nd_ids' returned by gSE called with params: '$gse_str'\n"; $stories = [ grep { !$_->{neverdisplay} } @$stories ]; }
# A kludge to keep Politics stories off the mainpage. The # proper fix would be to redesign story_topics_rendered to # include a weight in the (stoid,nexus_tid) tuple, and to # have gSE only select stories from its nexus list with that # weight or higher. Instead I've been asked to hardcode # an "offmainpage" boolean at story save time which will be # checked at story display time. -Jamie 2008-01-25 if ($gSkin->{skid} == $constants->{mainpage_skid}) { my $om_hr = { }; if ($stoid_in_str) { $om_hr = $gse_db->sqlSelectAllKeyValue('stoid, value', 'story_param', qq{stoid IN ($stoid_in_str) AND name='offmainpage' AND value != 0}); if (keys %$om_hr) { for my $story_hr (@$stories) { $story_hr->{offmainpage} = 1 if $om_hr->{ $story_hr->{stoid} }; } } } # XXX should only grep a story out if the story has # NO nexuses that the user has requested appear in # full on the mainpage $stories = [ grep { !$_->{offmainpage} } @$stories ]; }
#my $last_mainpage_view; #$last_mainpage_view = $slashdb->getTime() if $gSkin->{nexus} == $constants->{mainpage_skid} && !$user->{is_anon};
- use Data::Dumper;
- print STDERR "index.pl gse_hr: " . Dumper($gse_hr);
- print STDERR "index.pl gSE stories: " . Dumper($stories);
# We may, in this listing, have a story from the Mysterious Future. # If so, there are three possibilities: # 1) This user is a subscriber, in which case they see it (and its # timestamp gets altered to the MystFu text) # 2) This user is not a subscriber, but is logged-in, and logged-in # non-subscribers are allowed to *know* that there is such a # story without being able to see it, so we make them aware. # 3) This user is not a subscriber, and non-subscribers are not # to be made aware of this story's existence, so ignore it. my $future_plug = 0;
# Is there a story in the Mysterious Future? my $is_future_story = 0; $is_future_story = 1 if @$stories # damn you, autovivification! && $stories->[0]{is_future};
# Do we want to display the plug saying "there's a future story, # subscribe and you can see it"? Yes if the user is logged-in # but not a subscriber, but only if the first story is actually # in the future. If the user has a daypass, they don't get this # either. Just check the first story; they're in order. if ($is_future_story && !$user->{is_subscriber} && !$user->{has_daypass} && !$user->{is_anon} && $constants->{subscribe_future_plug}) { $future_plug = 1; }
return do_rss($reader, $constants, $user, $form, $stories, $skin_name) if $rss;
# Do we want to display the plug offering the user a daypass? my $daypass_plug_text = ; if ($constants->{daypass}) { # If this var is set, only offer a daypass when there # is a future story available. if (!$constants->{daypass_offer_onlywhentmf} || $is_future_story) { my $daypass_db = getObject('Slash::Daypass', { db_type => 'reader' }); my $do_offer = $daypass_db->doOfferDaypass(); if ($do_offer) { $daypass_plug_text = $daypass_db->getOfferText(); # On days where a daypass is being offered, for # users who are eligible, we give them that # message instead of (not in addition to) the # "please subscribe" message. $future_plug = 0; } } }
- # See comment in plugins/Journal/journal.pl for its call of
- # getSkinColors() as well.
- $user->{currentSection} = $section->{section};
Slash::Utility::Anchor::getSkinColors();
# displayStories() pops stories off the front of the @$stories array. # Whatever's left is fed to displaySlashboxes for use in the # index_more block (aka Older Stuff). # We really should make displayStories() _return_ the leftover # stories as well, instead of modifying $stories in place to just # suddenly mean something else. my $linkrel = {}; $Stories = displayStories($stories, $linkrel);
# damn you, autovivification! my($first_date, $last_date); if (@$stories) { ($first_date, $last_date) = ($stories->[0]{time}, $stories->[-1]{time}); $first_date =~ s/(\d\d\d\d)-(\d\d)-(\d\d).*$/$1$2$3/; $last_date =~ s/(\d\d\d\d)-(\d\d)-(\d\d).*$/$1$2$3/; }
my $StandardBlocks = displaySlashboxes($gSkin, $stories, { first_date => $first_date, last_date => $last_date } );
my $title = getData('head', { skin => $skin_name }); header({ title => $title, link => $linkrel }) or return;
if ($form->{remark} && $user->{is_subscriber} && $form->{sid}) { my $sid = $form->{sid}; my $story = $slashdb->getStory($sid); my $remark = $form->{remark}; # If what's pasted in contains a substring that looks # like a sid, yank it out and just use that. my $targetsid = getSidFromRemark($remark); $remark = $targetsid if $targetsid; if ($story) { my $remarks = getObject('Slash::Remarks'); $remarks->createRemark($remark, { uid => $user->{uid}, stoid => $story->{stoid} }); print getData('remark_thanks'); } }
my $metamod_elig = 0; if ($constants->{m2}) { my $metamod_reader = getObject('Slash::Metamod', { db_type => 'reader' }); $metamod_elig = $metamod_reader->metamodEligible($user); } slashDisplay('index', { metamod_elig => $metamod_elig, future_plug => $future_plug, daypass_plug_text => $daypass_plug_text, stories => $Stories, boxes => $StandardBlocks, });
footer(); #$slashdb->setUser($user->{uid}, { 'last_mainpage_view' => $last_mainpage_view }) if $last_mainpage_view; writeLog($skin_name);
- {
- use Proc::ProcessTable;
- my $t = new Proc::ProcessTable;
- my $procs = $t->table();
- PROC: for my $proc (@$procs) {
- my $pid = $proc->pid();
- next unless $pid == $$;
- my $size = $proc->size();
- if ($size > 10_000_000) {
- my $mb = sprintf("%.2f", $size/1_000_000);
- print STDERR "pid $$ VSZ $mb MB: just finished op '$form->{op}' sid '$form->{sid}' issue '$form->{issue}' skid '$gSkin->{skid}' uid '$user->{uid}'\n";
- last PROC;
- }
- }
- }
}
- Slash::Apache::User can turn a "/" request into an index.pl request
- if the user has index_classic set or the user-agent is MSIE 6.
- So, since this already is index.pl, be sure not to redirect to
- "/" if either of those things is true, since that would be an
- infinite redirection loop.
sub redirect_home_if_necessary {
my $user = getCurrentUser(); my $form = getCurrentForm(); my $script = ; if (!$user->{is_anon} && defined $form->{usebeta}) { my $usebeta = $form->{usebeta} eq '1'; my $index_classic = $usebeta ? undef : 1; if ($user->{index_classic} xor $index_classic) { my $slashdb = getCurrentDB(); $slashdb->setUser($user->{uid}, { index_classic => $index_classic }); $user->{index_classic} = $index_classic; } $script = '/' if $usebeta && !$form->{content_type} && $ENV{HTTP_USER_AGENT} !~ /MSIE [2-6]/; }
if ( $form->{op} && $form->{op} eq 'userlogin' && !$user->{is_anon} || $form->{upasswd} || $form->{unickname} ) { # Any login attempt, successful or not, gets # redirected to the homepage, to avoid keeping # the password or nickname in the query_string of # the URL (this is a security risk via "Referer"). # (If we've determined the user needs to go to # index2.pl, send them there.) Note that # $form->{returnto} is processed by # Slash::Apache::User::handler, which for reasons # of a mysterious bug defers the actual redirect # to be handled by this script. $script = $form->{returnto} || '/'; }
if ($script) { redirect($script); return 1; } return 0;
}
sub getDispModesForStories {
my($stories, $stories_data_cache, $user, $modes, $story_to_dispmode_hr) = @_;
my @story_always_topic = split (',', $user->{story_always_topic}); my @story_always_nexus = split (',', $user->{story_always_nexus}); my @story_full_brief_nexus = split (',', $user->{story_full_brief_nexus}); my @story_brief_always_nexus = split (',', $user->{story_brief_always_nexus}); my @story_full_best_nexus = split (',', $user->{story_full_best_nexus}); my @story_brief_best_nexus = split (',', $user->{story_brief_best_nexus});
my(%mp_dispmode_nexus, %sec_dispmode_nexus); $mp_dispmode_nexus{$_} = $modes->[0] foreach (@story_always_nexus, @story_full_brief_nexus, @story_full_best_nexus); $mp_dispmode_nexus{$_} = $modes->[1] foreach (@story_brief_best_nexus, @story_brief_always_nexus); $sec_dispmode_nexus{$_} = $modes->[2] foreach (@story_always_nexus); $sec_dispmode_nexus{$_} = $modes->[3] foreach (@story_full_brief_nexus, @story_brief_always_nexus); $sec_dispmode_nexus{$_} = $modes->[4] foreach (@story_full_best_nexus, @story_brief_best_nexus);
$story_to_dispmode_hr ||= {};
# Filter out any story we're planning on skipping up front @$stories = grep { getDispModeForStory($_, $stories_data_cache->{$_->{stoid}}, \%mp_dispmode_nexus, \%sec_dispmode_nexus, \@story_always_topic, $story_to_dispmode_hr) ne "none" } @$stories;
}
sub getDispModeForStory {
my($story, $story_data, $mp_dispmode_nexus_hr, $sec_dispmode_nexus_hr, $always_topic_ar, $dispmode_hr) = @_; my $constants = getCurrentStatic(); my $gSkin = getCurrentSkin(); my $slashdb = getCurrentDB(); my $skins = $slashdb->getSkins(); my $dispmode;
# sometimes this is uninit ... my $ps_nexus = $skins->{$story->{primaryskid}}->{nexus};
if ($gSkin->{nexus} != $constants->{mainpage_nexus_tid}) { $dispmode_hr->{$story->{stoid}} = "full" if $dispmode_hr; return "full"; }
# XXXNEWINDEX : Right now we do our best to handle this -- there is no user pref # to select whether a user wants to see this in brief vs full mode. For # now we just return "full" (individual non-nexus topic selection isn't used on # Slashdot currently) foreach (@$always_topic_ar) { $dispmode_hr->{$story->{stoid}} = "full" if $dispmode_hr; return "full" if $story_data->{story_topics_rendered}{$_}; }
if ($story_data->{story_topics_rendered}{$constants->{mainpage_nexus_tid}}) { $dispmode = $mp_dispmode_nexus_hr->{$ps_nexus}; $dispmode_hr->{$story->{stoid}} = $dispmode if $dispmode_hr && $dispmode; return $dispmode if $dispmode; $dispmode_hr->{$story->{stoid}} = "full" if $dispmode_hr; return "full"; }
# Sectional Story -- decide what we should do with it $dispmode = $sec_dispmode_nexus_hr->{$ps_nexus}; $dispmode_hr->{$story->{stoid}} = $dispmode if $dispmode_hr && $dispmode; return $dispmode if $dispmode;
# preference for sectional not defined -- go with default for site if ($constants->{brief_sectional_mainpage}) { $dispmode_hr->{$story->{stoid}} = "brief" if $dispmode_hr; return "brief"; } else { $dispmode_hr->{$story->{stoid}} = "none" if $dispmode_hr; return "none"; }
}
sub getSidFromRemark {
my($remark) = @_; my $regex = regexSid(); my($sid) = $remark =~ $regex; return $sid || ;
}
sub do_rss {
my($reader, $constants, $user, $form, $stories, $skin_name) = @_; my $gSkin = getCurrentSkin(); my @rss_stories;
my @stoids_for_cache = map { $_->{stoid} } @$stories; my $stories_data_cache; $stories_data_cache = $reader->getStoriesData(\@stoids_for_cache) if @stoids_for_cache;
getDispModesForStories($stories, $stories_data_cache, $user, [qw(full none full none none)]);
for (@$stories) { my $story = $reader->getStory($_->{sid}); $story->{introtext} = parseSlashizedLinks($story->{introtext}); $story->{introtext} = processSlashTags($story->{introtext}); $story->{introtext} =~ s{(HREF|SRC)\s*=\s*"(//[^/]+)} {$1 . '="' . url2abs($2)}sieg; push @rss_stories, { story => $story }; }
my $title = getData('rsshead', { skin => $skin_name }); my $name = lc($gSkin->{basedomain}) . '.' . $form->{content_type};
xmlDisplay($form->{content_type} => { channel => { title => $title, }, version => $form->{rss_version}, image => 1, items => \@rss_stories, rdfitemdesc => 1, rdfitemdesc_html => 1, }, { filename => $name, });
writeLog($skin_name); return;
}
- Should this method be in the DB library?
- absolutely. we should hide the details there. but this is in a lot of
- places (modules, index, users); let's come back to it later. -- pudge
sub saveUserBoxes {
my(@slashboxes) = @_; my $slashdb = getCurrentDB(); my $user = getCurrentUser(); return if $user->{is_anon}; $user->{slashboxes} = join ",", @slashboxes; $slashdb->setUser($user->{uid}, { slashboxes => $user->{slashboxes} });
}
sub upBid {
my($bid) = @_; my @a = getUserSlashboxes(); # Build the %order hash with the order in the values. my %order = ( ); for my $i (0..$#a) { $order{$a[$i]} = $i; } # Reduce the value of the block that's reordered. $order{$bid} -= 1.5; # Resort back into the new order. @a = sort { $order{$a} <=> $order{$b} } keys %order; saveUserBoxes(@a);
}
sub dnBid {
my($bid) = @_; my @a = getUserSlashboxes(); # Build the %order hash with the order in the values. my %order = ( ); for my $i (0..$#a) { $order{$a[$i]} = $i; } # Increase the value of the block that's reordered. $order{$bid} += 1.5; # Resort back into the new order. @a = sort { $order{$a} <=> $order{$b} } keys %order; saveUserBoxes(@a);
}
sub rmBid {
my($bid) = @_; my @a = getUserSlashboxes(); @a = grep { $_ ne $bid } @a; saveUserBoxes(@a);
}
- pass it how many, and what.
sub displayStories {
my($stories, $linkrel) = @_; my $reader = getObject('Slash::DB', { db_type => 'reader' }); my $constants = getCurrentStatic(); my $form = getCurrentForm(); my $user = getCurrentUser(); my $gSkin = getCurrentSkin(); my $ls_other = { user => $user, reader => $reader, constants => $constants }; my($today, $x) = (, 0);
- XXXSKIN I'm turning custom numbers of maxstories off for now, so all
- users get the same number. This will improve query cache hit rates and
- right now we need all the edge we can get. Hopefully we can get this
- back on soon. - Jamie 2004/07/17
- my $user_maxstories = $user->{maxstories};
- Here, maxstories should come from the skin, and $cnt should be
- named minstories and that should come from the skin too.
my $user_maxstories = getCurrentAnonymousCoward("maxstories"); my $cnt = $gSkin->{artcount_min}; my($return, $counter);
# get some of our constant messages but do it just once instead # of for every story my $msg; $msg->{readmore} = getData('readmore'); if ($constants->{body_bytes}) { $msg->{bytes} = getData('bytes'); } else { $msg->{words} = getData('words'); }
# Pull the story data we'll be needing into a cache all at once, # to avoid making multiple calls to the DB.
- my $n_future_stories = scalar grep { $_->{is_future} } @$stories;
- my $n_for_cache = $cnt + $n_future_stories;
- $n_for_cache = scalar(@$stories) if $n_for_cache > scalar(@$stories);
my @stoids_for_cache = map { $_->{stoid} } @$stories;
- @stoids_for_cache = @stoids_for_cache[0..$n_for_cache-1]
- if $#stoids_for_cache > $n_for_cache;
my $stories_data_cache; $stories_data_cache = $reader->getStoriesData(\@stoids_for_cache) if @stoids_for_cache;
my $dispmodelast = ""; my $story_to_dispmode_hr = {};
getDispModesForStories($stories, $stories_data_cache, $user, [qw(full brief full brief none)], $story_to_dispmode_hr);
# Shift them off, so we do not display them in the Older Stuff block # later (this simulates the old cursor-based method from circa 1997 # which was actually not all that smart, but umpteen layers of caching # makes it quite tolerable here in 2004 :) my $story; STORIES_DISPLAY: while ($story = shift @$stories) { my($tmpreturn, $other, @links);
$other->{dispmode} = $story_to_dispmode_hr->{$story->{stoid}};
# This user may not be authorized to see future stories; if so, # skip them. if ($story->{is_future}) { # If subscribers are allowed to see 0 seconds into the # future, future stories are off-limits. next if !$constants->{subscribe_future_secs}; # If the user is a subscriber or has a daypass, the # is_subscriber field will be set. If that field is # not set, future stories are off-limits. next if !$user->{is_subscriber} && !$user->{has_daypass}; # If the user is only an honorary subscriber because # they have a daypass, and honorary subscribers don't # get to see The Mysterious Future, future stories are # off-limits. next if !$user->{is_subscriber} && $user->{has_daypass} && !$constants->{daypass_seetmf}; }
# Check the day this story was posted (in the user's timezone). # Compare it to what we believe "today" is (which will be the # first eligible story in this list). If this story's day is # not "today", and if we've already displayed enough stories # to sufficiently fill the homepage (typically 10), then we're # done -- put the story back on the list (so it'll correctly # appear in the Older Stuff box) and exit. my $day = timeCalc($story->{time}, '%A %B %d'); my($w) = join ' ', (split / /, $day)[0 .. 2]; $today ||= $w; if (++$x > $cnt && $today ne $w) { unshift @$stories, $story; last; }
my @threshComments = split /,/, $story->{hitparade}; # posts in each threshold
$other->{is_future} = 1 if $story->{is_future};
#$other->{dispoptions}{new} = 1 if !$user->{is_anon} && $user->{last_mainpage_view} && $gSkin->{nexus} == $constants->{mainpage_skid} && $user->{last_mainpage_view} lt $story->{time};
my $story_data = $stories_data_cache->{$story->{stoid}};
$tmpreturn .= getData("briefarticles_begin") if $other->{dispmode} && $other->{dispmode} eq "brief" && $dispmodelast ne "brief"; $tmpreturn .= getData("briefarticles_end") if $dispmodelast eq "brief" && !( $other->{dispmode} && $other->{dispmode} eq "brief" );
$story->{commentcount} = $threshComments[0] if $story->{commentcount};
$other->{thresh_commentcount} = $user->{threshold} > -1 ? $threshComments[$user->{threshold} + 1] : $story->{commentcount};
$tmpreturn .= displayStory($story->{sid}, , $other, $stories_data_cache);
if ($other->{dispmode} eq "full") { my $readmore = $msg->{readmore}; if ($constants->{index_readmore_with_bytes}) { my $readmore_data = {}; if ($story->{body_length}) { if ($constants->{body_bytes}) { $readmore_data->{bytes} = $story->{body_length}; } else { $readmore_data->{words} = $story->{word_count}; } $readmore = getData('readmore_with_bytes', $readmore_data ); } }
push @links, linkStory({ 'link' => $readmore, sid => $story->{sid}, tid => $story->{tid}, skin => $story->{primaryskid}, class => 'more' }, , $ls_other); my $link;
if ($constants->{body_bytes}) { $link = "$story->{body_length} $msg->{bytes}"; } else { $link = "$story->{word_count} $msg->{words}"; }
if (!$constants->{index_readmore_with_bytes}) { push @links, linkStory({ 'link' => $link, sid => $story->{sid}, tid => $story->{tid}, mode => 'nocomment', skin => $story->{primaryskid}, }, , $ls_other) if $story->{body_length}; }
my @commentcount_link; my $thresh = $threshComments[1]; # threshold == 0
$commentcount_link[1] = linkStory({ sid => $story->{sid}, tid => $story->{tid}, 'link' => $story->{commentcount} || 0, skin => $story->{primaryskid} }, , $ls_other);
push @commentcount_link, $thresh, ($story->{commentcount} || 0); push @links, getData('comments', { cc => \@commentcount_link });
if ($story->{primaryskid} != $constants->{mainpage_skid} && $gSkin->{skid} == $constants->{mainpage_skid}) { my $skin = $reader->getSkin($story->{primaryskid}); my $url;
if ($skin->{rootdir}) { $url = $skin->{rootdir} . '/'; } elsif ($user->{is_anon}) { $url = $gSkin->{rootdir} . '/' . $story->{name} . '/'; } else { $url = $gSkin->{rootdir} . '/' . $gSkin->{index_handler} . '?section=' . $skin->{name}; }
push @links, [ $url, $skin->{hostname} || $skin->{title}, , 'section']; }
if ($user->{seclev} >= 100) { push @links, [ "$gSkin->{rootdir}/admin.pl?op=edit&sid=$story->{sid}", getData('edit'), , 'edit' ]; if ($constants->{plugin}{Ajax}) { my $signoff = slashDisplay("signoff", { stoid => $story->{stoid}, storylink => 1 }, { Return => 1 } ); push @links, $signoff; } }
# I added sid so that you could set up replies from the front page -Brian $tmpreturn .= slashDisplay('storylink', { links => \@links, sid => $story->{sid}, }, { Return => 1 });
}
$return .= $tmpreturn; $dispmodelast = $other->{dispmode}; } $return .= getData("briefarticles_end") if $dispmodelast eq "brief";
unless ($constants->{index_no_prev_next_day}) { my($today, $tomorrow, $yesterday, $week_ago) = getOlderDays($form->{issue}); $return .= slashDisplay('next_prev_issue', { today => $today, tomorrow => $tomorrow, yesterday => $yesterday, week_ago => $week_ago, linkrel => $linkrel, }, { Return => 1 }); } # limit number of stories leftover for older stories if desired $#$stories = ($gSkin->{older_stories_max} - 1) if ($gSkin->{older_stories_max} < @$stories) && ($gSkin->{older_stories_max} > 0);
return $return;
}
createEnvironment(); main();
1;