Previous/next article within specific tags?

Hello,

Is it possible to filter prev/next buttons to only go through entries which are tagged with the current page’s active tag? I’m making a portfolio site for my paintings, and the main gallery categories are filtered by tags (portraits, landscapes, still-lifes, etc.). I’ve managed to make it so that if someone clicks on a painting when the portfolio page is actively filtered by a tag (say portraits), then it links to the specific project page with the tag still active:

siteurl/portfolio/tag:portraits/project-slug

On this page, would it be possible to have the nex/prev buttons only pull from projects tagged as “portraits”?

I used tags here instead of grouping my paintings into subfolders within the portfolio folder because many painting fall into multiple categories.

Thanks!

Not sure, but it looks as if @AudioBear has written a plugin that might cover you: https://github.com/shoesforindustry/kirbycms-extensions/tree/master/plugins/uninextprev

Thanks! I was just looking at that. Unfortunately, my php and Kirby skills are barely above cut and paste. If @AudioBear’s plugin can be used to do what I’m looking for, I’m not sure how.

Not sure if this is what you want, but you can use a paginated array of pages / tags, in the demo Articles tagged ‘Law’ or if you don’t want the detail pages in the demo, Press tagged ‘Social+Media’.

You are basically going to have to set up you index pages as per the usual ‘article’ page examples for use with/out tags in the URL’s, see docs.

Assuming you have paginated array of the articles, these bits of code (not complete and untested) are an example for if tags are set in the URL. You also need code for it tags aren’t in URL):

// page template

// If any tags are set...
if(urldecode(param('tag'))) {

// Get our array of articles
$articles = $pages->find('articles')
                  ->children()
                  ->visible()
                  ->filterBy('tags', urldecode(param('tag')), ',')
                  ->sortby('date', 'asc')
                  ->flip()
                  ->paginate(3);
  
// Do some pagination
$pagination  = $articles->pagination();

//Call uniNextPrev plugin with pagination
$uniNextPrev = uninextprev(array('pagination' => $articles->pagination())); 


//..... some more code for when tags are not set and other stuff you might need.
));

// Then we are going to call our footer snippet with the uniNextPrev variables
snippet('footer', array(
  'nextPageURL'   => $uniNextPrev['nextPageURL'],
  'nextPageTitle' => $uniNextPrev['nextPageTitle'],
  'prevPageURL'   => $uniNextPrev['prevPageURL'],
  'prevPageTitle' => $uniNextPrev['prevPageTitle']
))

In the footer snippet we would have some code… something like this

<ul>
  <li>
    <?php if(isset($prevPageURL) AND $prevPageURL<>''): ?>
      <a href="<?php echo $prevPageURL ?>" rel="previous" title="<?php echo $prevPageTitle ?>" ><?php echo excerpt($prevPageTitle,18) ?>
      </a>
    <?php endif ?>
 </li>
 <li>
    <?php  if(isset($nextPageURL) AND $nextPageURL<>''): ?>
      <a href="<?php echo $nextPageURL ?>" rel="next" title="<?php echo $nextPageTitle ?>">
      <?php echo excerpt($nextPageTitle,18) ?>
      </a>
    <?php endif ?>
  </li>
<ul>

Hope this helps point you in the right direction?

Thanks, I really appreciate the response. I installed your plugin and am experimenting now…

In your example, I would want to click on an article tagged ‘Law’, and then on the article detail page, I would want the next/prev buttons to only cycle through articles tagged ‘Law’.

From the your Articles tagged ‘Law’ page, I would be able to force the tag ‘Law’ into the detail pages, like this:

But then I would need to filter the prev/next buttons for the detail page’s active tag (‘Law’).

Is this possible with your plugin?

1 Like

Okay, I figured it out!

In the end, I didn’t use $page->next() or @AudioBear’s plugin. The gist of what I came up with is pasted below, in case it is of use to anyone. (I’m sure it could be done much more elegantly, but I’m just happy that it works). Also, this is now live on my website:
http://jqdaily.com/portfolio/tag:figures

@AudioBear – thank you so much for your reply! It put me on the path to this solution.

-Joseph

<?php 
	$p=param('tag');
	$date=$page->date();
	if($p != ''):
    $prevarticles=$pages->find('portfolio')
    		  ->children()
                  ->visible()
                  ->filterBy('tags', $p, ',')
                  ->filterBy('date', '>', $date)
                  ->sortby('date', 'asc')
                  ->limit(1);

    $nextarticles=$pages->find('portfolio')
    		  ->children()
                  ->visible()
                  ->filterBy('tags', $p, ',')
                  ->filterBy('date', '<', $date)
                  ->sortby('date', 'desc')
                  ->limit(1);
    endif;
?>                  

<div id="next">

<?php if($p != ''): ?>

	<div class="next group">
	<?php foreach($prevarticles as $prevarticle): ?>
		<a href="<?php echo url('portfolio'),'/tag:',$p,'/',$prevarticle->slug(); ?>" title="View '<?php echo $prevarticle->title(); ?>'">Prev</a>
	<?php endforeach ?>
	
	<?php foreach($nextarticles as $nextarticle): ?>
		<a href="<?php echo url('portfolio'),'/tag:',$p,'/',$nextarticle->slug(); ?>" title="View '<?php echo $nextarticle->title(); ?>'">Next</a>
	<?php endforeach ?>
	</div>
	
<?php else: ?>  
	
	<div class="next group">
	<?php if($page->hasNextVisible()): ?>
		<a href="<?php echo $page->nextVisible()->url() ?>" title="View '<?php echo $page->nextVisible()->title() ?>'…">Prev</a>
	<?php endif ?>
		
	<?php if($page->hasPrevVisible()): ?>
		<a href="<?php echo $page->prevVisible()->url() ?>" title="View '<?php echo $page->prevVisible()->title() ?>'…">Next</a>
	<?php endif ?>
	</div>

<?php endif ?>

</div><!--next-->
2 Likes

This is how I did it. Don’t know if the code is fast/good/clean, but it seems to work really well.

Set the $tag you want the prev/next page to have:

$tag = 'sometag'; 

Get all pages with $tag:

foreach($site->index()->filterBy('tags', $tag, ',') as $item)
{
$arrayTags[] = $item;
}

This can be adjusted to your needs, e.g.:

foreach($pages->find('portfolio')->children()->visible()->filterBy('tags', $p, ',')->sortby('date', 'asc') as $item)
{
$arrayTags[] = $item;
}

Check for position of current page in array:

if (in_array($page, $arrayTags)) {
$key = array_search($page, $arrayTags);
}

Check for first and last page in array:

$count = count($arrayTags);
$lastElement = end($arrayTags);
$firstElement = $arrayTags[0];

The next page with $tag:

if($page == $lastElement) {
$next = $firstElement;
} else {
$next = $arrayTags[$key + 1];	
}

The prev page with $tag:

if($page == $firstElement) {
$prev = $lastElement;
} else {
$prev = $arrayTags[$key - 1];
}