how to modify Archives plugin?

Creating and modifying plugins.
Post Reply
camccli
Posts: 3
Joined: Wed May 13, 2026 7:38 pm

how to modify Archives plugin?

Post by camccli »

Hello, all.

The previous iteration of my blog stopped working at some point, so I just re-created everything. (It was easier than tracking down the problem (it's the lovely 500 internal server error - tried a few things but gave up); it's not that big of a blog, and there haven't been updates for a while.)

Having re-created it, I see there have been some changes to how Serendipity displays things. I've looked around and played with a few things, but have not been able to find where to do the modifications I want.

I would like to be able to have the archives list show up like this (like it used to):

blog archives
November 2017 (1)
August 2017 (1)
July 2017 (2)
April 2017 (1)
etc.

rather than showing nothing (because the plugin defaults to the last three months), and then the links to "recent" and "older". (I would also like to modify the display at the "older" link to be similar to the above - or at least not two columns.)

I'm using the 2k11 theme. EDIT: And Serendipity 2.6.0.

Thanks!


Cathleen
onli
Regular
Posts: 3048
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: how to modify Archives plugin?

Post by onli »

The plugin has some configuration options that might get you close. If you set "Show number of entries per category?" and "Hide archives link when no entries were made in that timespan (requires counting entries)" to Yes, that's not the result you want?

It's likely the plugin hasn't seen updates in a long while, so it's probably still the same version you remember. So the right configuration might get you what you want. But it's of course also possible something broke, then we can probably fix it.
camccli wrote: Wed May 13, 2026 8:03 pm (I would also like to modify the display at the "older" link to be similar to the above - or at least not two columns.)
The plugin sadly has no theming support so far, but it might be doable with some CSS. Could you describe a bit more of how you want these two links be displayed?
camccli
Posts: 3
Joined: Wed May 13, 2026 7:38 pm

Re: how to modify Archives plugin?

Post by camccli »

Hi, Onli.
onli wrote: Wed May 13, 2026 10:14 pm The plugin has some configuration options that might get you close. If you set "Show number of entries per category?" and "Hide archives link when no entries were made in that timespan (requires counting entries)" to Yes, that's not the result you want?
No, it's not.

I have "Show number of entries per category?" selected.

If I set "Hide archives link when no entries" to No, then I get this:

May 2026 (0)
April 2026 (0)
March 2026 (0)
February 2026 (0)
January 2026 (0)
Recent...
Older...

If I set it to Yes, then I get this:

Recent...
Older...

The most recent entry is from 2017. What I'd like is for it to show the last X months which have entries ("X" being "Number of items in the list").
onli wrote: Wed May 13, 2026 10:14 pm Could you describe a bit more of how you want these two links be displayed?
It currently looks like this, which I find visually confusing - I try to read it down instead of left to right, and the 2015 section gets a bit lost.

Image

So...

- Just a list straight down, or
- A list straight down the left column, then continuing in the right column (I realize this might not work for people with larger blogs).
- And in either case remove the "entries" word. (Or not.)

I only started using Serendipity last year (moved the blog over from Greymatter), so whatever version of the plugin was around then is what I was using. I'd saved off that working version of the blog after I got it set up, so can look at and compare the files there once I find out where to look.

Hope that all makes sense.

Thanks!
onli
Regular
Posts: 3048
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: how to modify Archives plugin?

Post by onli »

Hi
Okay. So the sidebar plugin and the archive page you showed stem from different places, even though the sidebar plugin links to the archive page. 2k11 has a template for the archive page, I think that's templates/2k11/entries_archives.tpl. You can edit it, for example change the text. If your old blog used a different theme that might explain the difference you noticed. If you do this, consider copying 2k11 to a separate folder and renaming it. Then your modifications won't get overwritten by the next serendipity version. You could then also delete the files you did not change.

To gjust et it not to be this kind of two column layout, you would change the css of 2k11. templates/2k11/style.css, should be mainly this code block at line 1000:

Code: Select all

    .archives_year {
        float: left;
        width: 48%;
    }
Removing the float line would probably be already enough to have it single columns. Better, create /templates/2k11/user.css and overwrite the CSS there, untested:

Code: Select all

    .archives_year {
        float: none; !important
        width: 100%; !important
    }
---

The sidebar archive on the other hand is defined in plugins/serendipity_plugin_archives/serendipity_plugin_archives.inc.php. Its code is not set up to get the last X months which have entries. I didn't see a replacement, maybe someone else has an idea. Otherwise, if you can write PHP you could modify the plugin - probably you'd use `serendipity_fetchEntries` to get the recent entries, check from when they are, get more if you don't have already X months filled.
camccli
Posts: 3
Joined: Wed May 13, 2026 7:38 pm

Re: how to modify Archives plugin?

Post by camccli »

onli wrote: Thu May 14, 2026 12:06 am So the sidebar plugin and the archive page you showed stem from different places, even though the sidebar plugin links to the archive page.
Thanks; I should've been more clear that I was asking two questions. (My main one was about the sidebar archives listing.)
onli wrote: Thu May 14, 2026 12:06 am If your old blog used a different theme that might explain the difference you noticed.
I was using 2k11 before.
onli wrote: Thu May 14, 2026 12:06 am To just get it not to be this kind of two column layout, you would change the css of 2k11. templates/2k11/style.css, should be mainly this code block at line 1000:
Will have a look - thanks!
onli wrote: Thu May 14, 2026 12:06 am The sidebar archive on the other hand is defined in plugins/serendipity_plugin_archives/serendipity_plugin_archives.inc.php. Its code is not set up to get the last X months which have entries.
Drat. I'll just leave it the way it is, then - I know nothing about PHP.

Appreciate your time!
onli
Regular
Posts: 3048
Joined: Tue Sep 09, 2008 10:04 pm
Contact:

Re: how to modify Archives plugin?

Post by onli »

I had an idea for how this might work with reasonable effort. I didn't add a config option, but changed the default behaviour. Want to give give it a try? Replace your plugins/serendipity_plugin_archives/serendipity_plugin_archives.inc.php with this code:

Code: Select all

<?php

if (IN_serendipity !== true) {
    die ("Don't hack!");
}

class serendipity_plugin_archives extends serendipity_plugin
{
    var $title = ARCHIVES;

    function introspect(&$propbag)
    {
        $propbag->add('name',          ARCHIVES);
        $propbag->add('description',   BROWSE_ARCHIVES);
        $propbag->add('stackable',     true);
        $propbag->add('author',        'Serendipity Team');
        $propbag->add('version',       '1.2');
        $propbag->add('configuration', array('title', 'frequency', 'count', 'show_count', 'hide_zero_count'));
        $propbag->add('groups',        array('FRONTEND_VIEWS'));
    }

    function introspect_config_item($name, &$propbag)
    {
        switch($name) {

            case 'title':
                $propbag->add('type',        'string');
                $propbag->add('name',        TITLE);
                $propbag->add('description', TITLE_FOR_NUGGET);
                $propbag->add('default',     ARCHIVES);
                break;

            case 'count' :
                $propbag->add('type', 'string');
                $propbag->add('name', ARCHIVE_COUNT);
                $propbag->add('description', ARCHIVE_COUNT_DESC);
                $propbag->add('default', 3);
                break;

            case 'frequency' :
                $propbag->add('type', 'select');
                $propbag->add('name', ARCHIVE_FREQUENCY);
                $propbag->add('select_values', array('months' => MONTHS, 'weeks' => WEEKS, 'days' => DAYS));
                $propbag->add('description', ARCHIVE_FREQUENCY_DESC);
                $propbag->add('default', 'months');
                break;

            case 'show_count':
                $propbag->add('type',        'boolean');
                $propbag->add('name',        CATEGORY_PLUGIN_SHOWCOUNT);
                $propbag->add('description', '');
                $propbag->add('default',     false);
                break;

            case 'hide_zero_count':
                $propbag->add('type',        'boolean');
                $propbag->add('name',        CATEGORY_PLUGIN_HIDEZEROCOUNT);
                $propbag->add('description', '');
                $propbag->add('default',     false);
                break;

            default:
                return false;
        }
        return true;
    }

    function generate_content(&$title)
    {
        global $serendipity;

        $title = $this->get_config('title', $this->title);

        $ts = mktime(0, 0, 0, date('m'), 1);

        $add_query = '';

        $category_set = isset($serendipity['GET']['category']);
        if ($category_set) {
            $base_query   = 'C' . (int)$serendipity['GET']['category'];
            $add_query    = '/' . $base_query;
        }

        $max_x = $this->get_config('count', 3);
        $show_count = serendipity_db_bool($this->get_config('show_count', 'false'));
        $hide_zero_count = serendipity_db_bool($this->get_config('hide_zero_count', 'false'));
        $freq = $this->get_config('frequency', 'months');

        echo '<ul class="plainList">' . "\n";

        if ($serendipity['dbType'] == 'sqlite' || $serendipity['dbType'] == 'sqlite3' || $serendipity['dbType'] == 'sqlite3oo') {
            $dist_sql = 'count(e.id) AS orderkey';
        } else {
            $dist_sql = 'count(DISTINCT e.id) AS orderkey';
        }

         $entries_query = "SELECT
                                timestamp
                           FROM {$serendipity['dbPrefix']}entries
                           ORDER BY timestamp ASC
                           LIMIT 1";

        $first_entry = serendipity_db_query($entries_query, true);
        $first_timestamp = $ts;
        if (is_array($first_entry)) {
            $first_timestamp = $first_entry['timestamp'];
        }

        $output = [];
        $last_round = false;
        while(count($output) < $max_x && ($ts >= $first_timestamp || $last_round)) {
            $current_ts = $ts;
            switch($freq) {
                case 'months' :
                    switch($serendipity['calendar']) {
                        default:
                        case 'gregorian':
                            $linkStamp = date('Y/m', $ts);
                            $ts_title = serendipity_formatTime("%B %Y", $ts, false);
                            $ts = mktime(0, 0, 0, date('m', $ts)-1, 1, date('Y', $ts)); // Must be last in 'case' statement
                            break;
                        case 'persian-utf8':
                            require_once S9Y_INCLUDE_PATH . 'include/functions_calendars.inc.php';
                            $linkStamp = persian_date_utf('Y/m', $ts);
                            $ts_title = serendipity_formatTime("%B %Y", $ts, false);
                            $ts = persian_mktime(0, 0, 0, persian_date_utf('m', $ts)-1, 1, persian_date_utf('Y', $ts)); // Must be last in 'case' statement
                            break;
                    }
                    break;
                case 'weeks' :
                    switch($serendipity['calendar']) {
                        default:
                        case 'gregorian':
                            $linkStamp = date('Y/\WW', $ts);
                            $ts_title = WEEK . ' '. date('W, Y', $ts);
                            $ts = mktime(0, 0, 0, date('m', $ts), date('d', $ts)-7, date('Y', $ts));
                            break;
                        case 'persian-utf8':
                            require_once S9Y_INCLUDE_PATH . 'include/functions_calendars.inc.php';
                            $linkStamp = persian_date_utf('Y/\WW', $ts);
                            $ts_title = WEEK . ' '. persian_date_utf('W، Y', $ts);
                            $ts = persian_mktime(0, 0, 0, persian_date_utf('m', $ts), persian_date_utf('d', $ts)-7, persian_date_utf('Y', $ts));
                            break;
                    }
                    break;
                case 'days' :
                    switch($serendipity['calendar']) {
                        default:
                        case 'gregorian':
                            $linkStamp = date('Y/m/d', $ts);
                            $ts_title = serendipity_formatTime("%B %e. %Y", $ts, false);
                            $ts = mktime(0, 0, 0, date('m', $ts), date('d', $ts)-1, date('Y', $ts)); // Must be last in 'case' statement
                            break;
                        case 'persian-utf8':
                            require_once S9Y_INCLUDE_PATH . 'include/functions_calendars.inc.php';
                            $linkStamp = persian_date_utf('Y/m/d', $ts);
                            $ts_title = serendipity_formatTime("%e %B %Y", $ts, false);
                            $ts = persian_mktime(0, 0, 0, persian_date_utf('m', $ts), persian_date_utf('d', $ts)-1, persian_date_utf('Y', $ts)); // Must be last in 'case' statement
                            break;
                    }
                    break;
            }
            $link = serendipity_rewriteURL(PATH_ARCHIVES . '/' . $linkStamp . $add_query . '.html', 'serendipityHTTPPath');

            $html_count = '';
            $hidden_by_zero_count = false;
            if ($show_count) {
                switch($freq) {
                    case 'months':
                        $end_ts = $current_ts + (date('t', $current_ts) * 24 * 60 * 60) - 1;
                        break;
                    case 'weeks':
                        $end_ts = $current_ts + (7 * 24 * 60 * 60) - 1;
                        break;
                    case 'days':
                        $end_ts = $current_ts + (24 * 60 * 60) - 1;
                        break;
                }

                $ec = serendipity_fetchEntries(
                    array($current_ts, $end_ts),
                    false,
                    '',
                    false,
                    false,
                    null,
                    '',
                    false,
                    true,
                    $dist_sql,
                    '',
                    'single',
                    false, $category_set // the joins used
                );

                if (is_array($ec)) {
                    if (empty($ec['orderkey'])) {
                        $ec['orderkey'] = '0';
                    }
                    $hidden_by_zero_count = $hide_zero_count && ( $ec['orderkey'] == '0');
                    $html_count .= ' (' . $ec['orderkey'] . ')';
                }
            }

            if (!$hidden_by_zero_count) {
                $output[] = '    <li><a href="' . $link . '" title="' . $ts_title . '">' . $ts_title . $html_count . '</a></li>' . "\n";
            }

            // With few entries, the timestamp of the last iteration can be before the first entry.
            // So run one more time to be sure we got all entries.
            if ($ts < $first_timestamp && $last_round) {
                break;
            }
            if ($ts < $first_timestamp) {
                $last_round = true;
            } 
        }

        $output = array_slice($output, 0, $max_x);
        echo join($output);
        echo '    <li><a href="'. $serendipity['serendipityHTTPPath'] . $serendipity['indexFile'] . '?frontpage">' . RECENT . '</a></li>' . "\n";
        echo '    <li><a href="'. serendipity_rewriteURL(PATH_ARCHIVE . $add_query) .'">' . OLDER . '</a></li>'. "\n";
        echo '</ul>' . "\n";
    }

}

?>
It's not an efficient implementation - it iterates over the timespans until it finds enough entries, mirroring the old approach. But if the performance impact is not too hard on your system (which would be almost a worst case, if your last entries are from 2017) it could be good enough.
Post Reply