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;
}
Share or Bookmark This Post:


Comments

RSS Comments Feed


asundrus's Avatar

asundrus

Nice job, working perfectly, actually alot better than my original idea, which was adding all months in my sidebare, I know made a link for 2009 instead, which is more simpler, so again, thanks alot for your efforts.

Matt's Avatar

Matt

Thanks asundrus, I'm glad you found it useful. Your idea about the sidebar isn't a bad idea either, it shouldn't be too hard to make a WordPress style sidebar "archives" list function that works in conjunction with this one.

Poppoll's Avatar

Poppoll

As always great job Matt.
Thanks,
PP

Sven - Philippe's Avatar

Sven - Philippe

As usual, it doesn't work for me. :-D
Nothing is extracted:
(http://carnet.hiseo.fr/archive/)
Another bug due to the DB prefix?

Matt's Avatar

Matt

Sven, yep, it's the DB prefix again :), I threw this one up in a real hurry too, so I was expecting problems.

I've updated the function now.

Sven - Philippe's Avatar

Sven - Philippe

"(...) so I was expecting problems."
And I came.
Thanks a lot Matt. It's working like a charme now.

Matt's Avatar

Matt

Sven,

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's Avatar

Sven - Philippe

That makes sense, Matt. I placed setlocale(LC_ALL, 'fr_FR.utf8'); at the top of my snews.
And now my snews speaks french better than inspecteur Clouseau. :-D

Have a nice day pal.

Poppoll's Avatar

Poppoll

Matt,
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's Avatar

Matt

Hey PP, I see the problem, it's b/c your install is in a subfolder, that subfolder is part of the request_uri.

<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's Avatar

Poppoll

Yes yes yes that's it... :-)
Thanks again Matt.

PP

Fred K's Avatar

Fred K

Thanks for this Matt. Very useful and ever so easy to hack for own purposes (I needed output in lists and with long month names but that's a cinch with the things included in the setup.)

konga's Avatar

konga

Just found that mod, which is another great one!!

Thanks again for all your work for the snews community ;)

Patric's Avatar

Patric

Damn this was a better one...

Sven/Philippe's Avatar

Sven/Philippe

Uh oh.
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's Avatar

Matt

Sven, something must be wrong with an article date, as that part is as simple as it gets. Try running this SQL command in your DB admin tool;


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's Avatar

Sven/Philippe

As usual it was a Sven bug which has been corrected now. Thanks a lot for having helped.

I just checked my spam folder: there is no mail from you in it. ???

Matt's Avatar

Matt

Looks like 1and1 didn't like my MX record and kicked it back, I think I've fixed that now. I've removed your notification entry, so next time you try to subscribe, it should hopefully send you the verify email.

That's why it's still very beta :P

Sven/Philippe's Avatar

Sven/Philippe

Oh okey. I was wondering if it was sent by sea or airmail. I'll be waiting for internet in Europe.

Sven/Philippe's Avatar

Sven/Philippe

Man you're a genious!!!
It works and it's damn great!
Where do I send my karma?

Matt's Avatar

Matt

LOL Sven, thanks.

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's Avatar

Daichsian

Matt,

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's Avatar

Matt

Mine is just customized further, that's all :)

It just spits out a list of all cats/articles, basically a copy and paste of most of the sitemap function, with pages removed :)




(optional, not publicly displayed)


(optional)

Subscribe

RSS Feed

Archives

Powered by HTML5

HTML5 Powered with CSS3 / Styling, Multimedia, and Semantics