Compact archives for sNews 1.7
Anyone that's running sNews and writes as many articles as me has no doubt encountered the limitations of the current archives page. Basically it's just an enormously long chronological list.
Here's a handy little replacement function to display the archives by year, with clickable months if in fact the month contains articles. A user can click a specific month to view listings from only that month, or by year to view the entire year's articles. View my archives page for a demo.
First add the following to your language file;
#compact archives $l['archive_by_date'] = 'By Date';
Now upload your language file.
OK, now for the logic, this is a simple drop-in replacement archive function, so the first step is ...as always... BACK-UP your snews.php file and work off of a copy. Now find the function archive and rename it, I always append "_orig" when renaming function, so I can easily go back, so rename it archive_orig. Now copy the new archive function into your snews.php file, again, I always put new functions at the bottom just above the closing php tag when possible, to separate from the original core code.
// ARCHIVE - COMPACT STYLE
function archive($start = 0, $size = 200) {
echo '<h2><a href="'._SITE.'archive/">'.l('archive').'</a>';
$break = explode("/",cleanXSS($_SERVER['REQUEST_URI']));
$count = count($break);
$months = array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12");
if (in_array($break[$count-2], $months)) { //month is requested
$year = $break[$count-3];
$month = $break[$count-2];
} elseif(strlen($break[$count-2]) == '4') {//just the year requested
$year = $break[$count-2];
}
if ($year >= '1900' && $year <= date('Y')) { // not a BS year
$a1 = " AND YEAR(date) = $year";
echo ' / <a href="'._SITE.'archive/'.$year.'/">'.$year.'</a>';
}
if (checkdate($month,1,2001)) { // not a BS month
$date_placeholder = strtotime("$month/01/2001");
$a2 = " AND MONTH(date)=$month";
$month_name = strftime("%B", $date_placeholder); // Full month name, based on the locale
echo ' / '.$month_name;
}
if (!$a1 && !$a2) { // YEAR/Month not set, display front page
echo '</h2><h6>'.l('archive_by_date').'</h6><div class="archive_date"><p>';
$query = "SELECT DISTINCT YEAR(date) AS year FROM "._PRE."articles a, "._PRE."categories c
WHERE a.published='1'
AND a.visible='YES'
AND c.published='YES'
AND a.category=c.id
AND a.date <= NOW()
ORDER BY year DESC";
$result = mysql_query($query);
while ($row = mysql_fetch_array($result)) {
$i = "0";
$year = $row['year'];
echo '<a href="'._SITE.'archive/'.$year.'/" title="'.$year.'">'.$year.'</a> ';
$month_query = "SELECT DISTINCT MONTH(date) AS month FROM "._PRE."articles a, "._PRE."categories c
WHERE YEAR(date) = '$year'
AND a.published='1'
AND a.visible='YES'
AND c.published='YES'
AND a.category=c.id
AND a.date <= NOW()
ORDER BY month ASC";
$month_result = mysql_query($month_query);
$rows = array();
while($r = mysql_fetch_assoc($month_result)) {array_push($rows, $r);}
for ($month = 1; $month <= 12; $month += 1) {
$date_placeholder = strtotime("$month/01/2001");
$month_name = strftime("%B", $date_placeholder); // Full month name, based on the locale
$month_abbrev = strftime("%b", $date_placeholder);// Abbreviated month name, based on the locale
if ($rows[$i]['month'] == $month) {
echo ' <a href="archive/'.$year."/".$month.'/" title="'.$month_name.' '.$year.'">'.strtolower($month_abbrev).'</a> ';
$i++;
} else {
echo ' '.strtolower($month_abbrev).' ';
}
}
echo "<br />";
}
echo '</p></div>';
} else { // Year and/or Month selected, display the appropriate articles
echo '</h2>';
$query = 'SELECT id FROM '._PRE.'articles'.'
WHERE position = 1
AND published = 1
AND visible = \'YES\'
'.$a1.'
'.$a2.'
ORDER BY date DESC
LIMIT '."$start, $size";
$result = mysql_query($query);
$count = mysql_num_rows($result);
if ($count === 0) {
echo '<p>'.l('no_articles').'</p>';
} else {
while ($r = mysql_fetch_array($result)) {
$or_id[] = 'a.id ='.$r['id'];
}
$or_id = implode(' OR ',$or_id);
$query = 'SELECT
title,a.seftitle AS asef,a.date AS date,
c.name AS name,c.seftitle AS csef,
x.name AS xname,x.seftitle AS xsef
FROM '._PRE.'articles'.' AS a
LEFT OUTER JOIN '._PRE.'categories'.' as c
ON category = c.id
LEFT OUTER JOIN '._PRE.'categories'.' as x
ON c.subcat = x.id
WHERE ('.$or_id.')
AND a.published = 1
AND c.published =\'YES\'
AND (x.published =\'YES\' || x.published IS NULL)
ORDER BY date DESC
LIMIT '."$start, $size";
$result = mysql_query($query);
$month_names = explode(', ', l('month_names'));
echo '<div class="arc_list"><p>';
while ($r = mysql_fetch_array($result)) {
$year = substr($r['date'], 0, 4);
$month = substr($r['date'], 5, 2) -1;
$day = substr($r['date'], 8, 2);
$month_name = (substr($month, 0, 1) == 0) ? $month_names[substr($month, 1, 1)] : $month_names[$month];
if ($last <> $year.$month) {
echo '<strong>'.$month_name.', '.$year.'</strong><br />';
}
$last = $year.$month;
$link = isset($r['xsef']) ? $r['xsef'].'/'.$r['csef'] : $r['csef'];
echo l('divider').' <a href="'._SITE.$link.'/'.$r['asef'].'/">
'.$r['title'].' ('.$r['name'].')</a><br />';
}
echo'</p></div>';
}
}
}
OK, now upload your modified sNews.php file and then check out your archive page, it should look similar to mine now.
You may also add styles to your archive, the DIV containing the date list on the front page has a class of archive_date, and the actual article listings are inside a div with the class of arc_list, these are the styles I use, feel free to use this code if you like;
.archive_date p {
line-height:1.6em;
font-family:"lucida console";
font-size:1.1em;
text-transform:uppercase;
text-align:justify;
}
.arc_list p {
text-align:left;
}
.arc_list p a {
color:#386E80;
}
Comments
RSS Comments Feed
asundrus
Matt
Poppoll
Thanks,
PP
Sven - Philippe
Nothing is extracted:
(http://carnet.hiseo.fr/archive/)
Another bug due to the DB prefix?
Matt
I've updated the function now.
Sven - Philippe
And I came.
Thanks a lot Matt. It's working like a charme now.
Matt
Looks good, ecept it appears your PHP locale is set to English, which results in "March" instead of "Mars".
This is an easy runtime fix; you can either add this to the top of your snews.php file to make it run French (I assume that's French :P) language;
<?php
setlocale(LC_ALL , 'fr_FR');
?>
or add this on the first line of the archives function to just make date/time localized to French;
<?php
setlocale(LC_TIME , 'fr_FR');
?>
Let me know if that doesn't make sense, or you need any help.
Sven - Philippe
And now my snews speaks french better than inspecteur Clouseau. :-D
Have a nice day pal.
Poppoll
I have a problem with this mod.
The years and months are correctly displayed on the archive page.
But when I click a month or a year, nothing happens..
I use a db prefix.
Online at http://nieuwerkerken-aalst.be/snews/archive/
PP
Matt
<strong>I have updated this function to work with subfolders now</strong>. Should work no matter no many folders deep you install sNews now.
Poppoll
Thanks again Matt.
PP
Fred K
konga
Thanks again for all your work for the snews community ;)
Patric
Sven/Philippe
Hey Matt when you got time check out my archive.
http://on-air.hiseo.fr/archive
There's a bug with this extra line withe a year=0.
There's something to see with the server: locally I don't have this extra line.
Weirdo.
Matt
SELECT DISTINCT YEAR(date) AS year FROM articles
ORDER BY year DESC;
See what that returns, and don't forget your table prefix :)
Oh yeah, and check your spam folder for the email comment notification stuff, seems like a lot the notification emails are ending up in people's spam folders... :/
Sven/Philippe
I just checked my spam folder: there is no mail from you in it. ???
Matt
That's why it's still very beta :P
Sven/Philippe
Sven/Philippe
It works and it's damn great!
Where do I send my karma?
Matt
There's still a few features I need to finish on the notification mod, once I finish and release my spam mod I'll get back to working on it again.
I use a cronjob to send batch notifications, as an example, if you're subscribed to 3 articles and they each get 2 new comments before the cronjob, then you'll only get 1 email, notifying you of the new comments, with the links to each article, etc.
Another thing you may notice is if you respond to a new comment before the cronjob is run, it won't send that one to you, as you've obviously seen it if you've already responded to it.
Daichsian
a nice one mod! But I have a question like allways :/
How did you get your archive like so:
By Date
By Category
? my archive is on By Date?! :D
p.s.: Kick my ass for bottering you so much!
David
Matt
It just spits out a list of all cats/articles, basically a copy and paste of most of the sitemap function, with pages removed :)