Search

Awesome. I have it adjusted with your changes. I made the constants more specific. It's all working on my site. I just need to make a utility to display the next/prev links on the page.

<?php

    require_once(TOOLKIT . '/class.datasource.php');

    Class datasourceneighbours extends Datasource{

        ### Name of dependent DS
        const articlesDSHandle = 'articles';
        ### Table ID for post date
        const dateFieldID = 'sym_entries_data_29';
        ### Table ID for published checkbox
        const publishFieldID = 'tbl_entries_data_30';

        function about(){
            return array('name' => 'Neighbours');   
        }

        function allowEditorToParse(){
            return false;
        }

        function __construct(&$parent, $env=NULL, $process_params=true){
            parent::__construct($parent, $env, $process_params);
            $this->_dependencies = array('$ds-' . self::articlesDSHandle);
        }

        function grab(&$param_pool){
            $entry_id = (int)$param_pool['ds-' . self::articlesDSHandle][0];
            $entry_date = $this->_Parent->Database->fetchVar('local', 0, "SELECT `local` FROM `".self::dateFieldID."` WHERE `entry_id` = $entry_id LIMIT 1");

            ### PREVIOUS
            $sql = "SELECT t1.`entry_id` 
                         FROM `".self::dateFieldID."` AS t1
                         LEFT JOIN `".self::publishFieldID."` AS t2 ON t1.entry_id = t2.entry_id
                         WHERE t1.`local` < $entry_date 
                         AND t2.value = 'yes'
                         ORDER BY t1.`local` DESC LIMIT 1";
            $param_pool['ds-neighbours'][] = $this->_Parent->Database->fetchVar('entry_id', 0, $sql);

            ### NEXT
            $sql = "SELECT t1.`entry_id` 
                         FROM `".self::dateFieldID."` AS t1
                         LEFT JOIN `".self::publishFieldID."` AS t2 ON t1.entry_id = t2.entry_id
                         WHERE t1.`local` > $entry_date 
                         AND t2.value = 'yes'
                         ORDER BY t1.`local` ASC LIMIT 1";
            $param_pool['ds-neighbours'][] = $this->_Parent->Database->fetchVar('entry_id', 0, $sql);
        }

    }

?>

Allen's method for getting the prev/next entries without resorting to a custom DS can be improved upon so there are no redundant elements. I think he also might not have explained it clearly enough, so I will try. It obviously depends on your needs whether a custom DS or the following method will be best.

  1. Create a data source called "Main Entry" and add all the filters it needs, such as title (which is filtered using the URL param Value "{$entry-handle}"), category, undrafted, etc.
  2. Make sure "Main Entry" is set to Show a maximum of "1" result(s). Also make sure to Sort By Date - where Date is the field used to determine how the prev/next entries are ordered. (Note: this needs to be a date field as of 2.0b5, but in a future version it should be possible to order prev/next by any field, e.g. alphabetically by title.)
  3. Set the Param Output for "Main Entry" to the same as the Sort By option. The param $ds-main-entry will be created with this value.
  4. Create two duplicates of "Main Entry" - "Previous Entry" and "Next Entry". In each of these, remove the title URL param filter, set Param Output to None, and set Show page "2" of results. You may also want to change which elements are included in the XML.
  5. Add a Date filter for "Previous Entry" with Value "2000-01-01 to {$ds-main-entry}". Set Sort Order to Descending.
  6. Add a Date filter for "Next Entry" with Value "{$ds-main-entry} to 2500-01-01". Set Sort Order to Ascending.
  7. Attach all 3 data sources to the page.

I'm not sure this will work because the param output for the date is like this:

$ds-articles              '05/20/08'

It would need to be this 2008-05-20 so I can do a range with {$ds-articles} to 2500-01-01

The date is coming from a 'date field' and I'm using beta version 5.

The date field should work with forward slashes as well as hyphens.

Unfortunately you might run into problems if you have more than one entry on a given day. The range doesn't take into consideration time, which means if you have 2 entries, and a day based range, you're not guaranteed to get the next/previous. That said, it will work fine if you have no more than a single entry on any given day.

In RC1 this problem is fixed by allowing date ranges to accept dates with time. E.G. 2007-06-10 13:42:11 to {$today}

The date field should work with forward slashes as well as hyphens.

Yes, but you are comparing different amounts of numbers in a different order. I think that's why it isn't working for me.

I also tried changing the next/prev DSs to do a range like {$ds-articles} to 01/01/09 and it still didn't pull data for the next article. Maybe I'm not doing it correctly ...

The multiple article per day glitch would be a problem, though. With RC1 coming up, I think this option will do what I want without a custom DS. For now, the custom DS seems to be just fine. Thanks for the input on this.

Yes, but you are comparing different amounts of numbers in a different order. I think that's why it isn't working for me.

Ahh, yes. You're right. The format needs to be YYYY-MM-DD otherwise it won't work. Add the following function to /lib/toolkit/fields/field.date.php:

public function getParameterPoolValue($data){
    return DateTimeObj::get('Y-m-d', $data['local']);
}

That should give it to you in the correct format. And as mentioned before, RC1 will introduce a time as well, Y-m-d H:i:s

Hrm, scratch that. there is actually a limitation to do with the param pool. I've instead patched 2 files which will

  1. remove that limitation,
  2. add the above code (with time support); and also,
  3. introduce syntax: (earlier|later) than DATE. E.G. later than {$ds-articles}

Drop class.datasource.php into symphony/lib/toolkit/ and field.date.php into symphony/lib/toolkit/fields/

Set up 2 DS's. One with a date filter of ealier than {$ds-articles} and the other with later than {$ds-articles}

Fingers crossed this works properly.

introduce syntax: (earlier|later) than DATE. E.G. later than {$ds-articles}

Nice!

Nice is right!

OK, I have applied the patch and $ds-articles is now showing the correct date format with hour and seconds. Here's an example:

$ds-articles    '2007-10-29 22:42:00'

But I still don't get any results with my next/prev DSs. I set things up just like Scott explained above only using the new later than {$ds-articles} filters.

  <article-next>
    <section id="6" handle="blog">Blog</section>
    <error>No Records Found.</error>
  </article-next>

I did notice that the XML the date field in my articles produces looks like this:

<date time="22:42" weekday="1">2007-10-29</date>

I don't see seconds in there and the date is split up. Would that cause the date filter to not work?

Hrm, I did this on a fresh copy of Rev5, so not sure. At line 258 of field.date.php put print_r($match); die(); and tell me if you get any output.

I get this:

Array ( [0] => later than 2008-05-26 12:43:12 [1] => later [2] => 2008-05-26 12:43:12 )

I do get a result if I change the value of the date filter to {$ds-articles} instead of later than {$ds-articles}.

Okay, that means it's getting in there. This is a silly question, but is there actually a 'next' article in the system? What about previous, is that working?

I think you have a bug in your patch.

I double checked everything and noticed a typo in my previous DS. Fixed that and I got previous articles, but the next still didn't work. I then tried to manually add the date 2038-01-19 03:14:08 as a range instead of using the later than range you set up in the patch. It didn't work either, then I changed it to 2009-01-19 03:14:08 and it worked!

I put my DS back to using the later than range and edited field.date.php on line 266

I changed the date from this:

case 'later': $string = DateTimeObj::get('Y-m-d H:i:s', $time+1) . ' to 2038-01-19 03:14:08'; break;

to this:

case 'later': $string = DateTimeObj::get('Y-m-d H:i:s', $time+1) . ' to 2037-01-19'; break;

and it started returning results.

Maybe you can't go past 2037 in unix time on my server because of the Year 2038 Problem?

Maybe you can't go past 2037 in unix time on my server because of the Year 2038 Problem?

Strange, but I think it is to do with the timezone since 2038-01-19 03:14:08 works for us, however there is no harm in setting it to be a few days before the 2038 problem date.

Ah, I didn't think about the time zone difference. Oh well, it works now. Yay!

Ok, it’s been more than two years since the last post on this topic. I’m using Symphony 2.0.7 and the “previous/next-thing” works just fine…as long as I’m not having multiple items on the same day.

Alistair wrote:

Unfortunately you might run into problems if you have more than one entry on a given day. The range doesn’t take into consideration time, which means if you have 2 entries, and a day based range, you’re not guaranteed to get the next/previous. That said, it will work fine if you have no more than a single entry on any given day.

In RC1 this problem is fixed by allowing date ranges to accept dates with time. E.G. 2007-06-10 13:42:11 to {$today}

It seems that this issue not been addressed since then? Am I missing something?

I’ve gotten Next/previous buttons to work on my portfolio site using only regular Symphony data sources. http://design.joshnichols.com/

Although, mine are based on the order I’ve set up using the Order entries field. Using the date field should work the same way.

You need three DSs (in addition to your “entry” DS).

  • Current entry
  • Next entry
  • Previous entry

Current entry is the current post. Make the param output be the entry’s date

Next entry uses the current entry parameter value in it’s DS filtering.

mysql: value > {$ds-current-entry}

Then show a maximum of 1 result.

Previous entry works the same way, just reverse the greater than to less than in the DS filter.

mysql: value < {$ds-current-entry}

This should give you all the data you need to build your next/previous buttons.

The only catch would be if Symphony 2.0.7 only outputs dates in you params that don’t include hours and seconds. Something like: 2009-08-22 instead of 2009-08-22 01:54:45 1:54 am This might be the problem you are having. I remember older versions of Symphony didn’t output the whole date in parameters.

In that case, I’d upgrade to Symphony 2.0.8 and try it. I’d do that anyway since 2.0.7 has a vulnerability concern that just poped up.

I just tested in Symphony 2.0.7 and the date field will return a date like this in a parameter:

'2010-07-17 20:32:00'

So it should work in your version of Symphony.

I’m using a next/previous article method in 2.0.8RC3 that employs four data sources where two of them are custom data sources. You can find the files here. This is based on someone else’s approach but I’ve lost the link.

Thank you both for your answers.

@MrBlank: As suggested earlier in this thread I have created three datasources: * current (Parameter Output: PublishDate[Date]) * next * prev

The output parameter does contain the time correctly: $ds-current -> ‘2010-07-17 17:03:00’

In datasource ‘next’ I’ve set up a filter for field ‘PublishDate’ with the following value: ‘later than {$ds-current}’

In datasource ‘prev’ I’ve set up a filter for field ‘PublishDate’ with the following value: ‘earlier than {$ds-current}’

With the above setup I’m still encountering the problem when there are multiple entries for one day. I’m far from being a PHP-expert, but I delved into the code of symphony/lib/toolkit/fields/field.date.php and I assume my problem is being caused by using the keywords ‘later than’ and ‘earlier than’. This triggers the function __buildRangeFilterSQL() in which an SQL-statement is constructed that doesn’t seem to take the time into consideration.

$where .= " AND (DATE_FORMAT(`t$field_id".$this->key."`.value, '%Y-%m-%d') >= '".DateTimeObj::get('Y-m-d', strtotime($date['start'])) ...

It seems to do the right thing if you can invoke a call to __buildSimpleFilterSQL() where the time is used.

$where .= " AND DATE_FORMAT(`t$field_id".$this->key."`.value, '%Y-%m-%d %H:%i:%s') IN ('".@implode("', '", $data)."') ";

Can you please tell me how I can use the filter values that you suggest? Maybe your filter is using the ‘simple’ routine. Should I use the following as the value when creating the filter?

“mysql: value > {$ds-current}”

When I do just that I don’t get any results from the prev/next datasources. I also tried the following - not yielding any results either:

“value > {$ds-current}” or this: “> {$ds-current}”

@wisolman: Good to know there’s a workaround that does the trick. I will resort to using your solution if I cannot work it out using the ‘standard way’. Also I will first have to learn how to implement these custom data sources. Is there any tutorial or resource on how to get this done and where to put the code you supplied? Sorry, I’m still a Symphonoob.

Thanks again for your help so far.

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details