Jump step in a collection of pages - Back and forward

I made a function to jump to a page, forward or reversed with a number of steps. If it hits the end it will loop pass by it so it will always find a page, as long as there are siblings.

The function with variations:

Direction, steps and page object is needed.

page_object_jump( 'reverse', 2, $page );
page_object_jump( 'forward', 3, $page );

The code

function page_object_reverse_one( $item ) {
	if ( $item->hasPrev() ) {
		$obj = $item->prev();
	} else {
		$obj = $item->siblings()->last();
	}
	return $obj;
}

function page_object_forward_one( $item ) {
	if ( $item->hasNext() ) {
		$obj = $item->next();
	} else {
		$obj = $item->siblings()->first();
	}
	return $obj;
}

function page_object_jump( $direction, $steps, $item ) {
	$item = ( ! empty( $item ) ) ? $item : page();
	for( $i = 0; $i < $steps; $i++ ) {
		if( $direction == 'reverse' ) {
			$item = page_object_reverse_one( $item );
		} elseif( $direction == 'forward' ) {
			$item = page_object_forward_one( $item );
		}
	}
	return $item;
}

$page_object = page_object_jump( 'reverse', 2, $page );
echo $page_object->title();

Untested, I may have the direction of my addition / subtraction and first / last the wrong way round, but this might be simpler:

function page_object_jump( $direction, $steps, $item ) {
	$item = ( ! empty( $item ) ) ? $item : page();
        $siblings = $item->siblings();
        $index = $siblings->indexOf($item);

        if( $direction === 'reverse' ) {
            if( ( $index + $steps ) > ( $siblings->count() - 1 ) ) {
                return $siblings->last();
            }
            return $siblings->nth($index + $steps);
        }
        else if( $direction === 'forward' ) {
            if( ( $index - $steps ) < 0 ) {
                return $siblings->first();
            }
            return $siblings->nth($index - $steps);
        }
	return $item;
}

Seems nice! I just tested it and the result are not the same. It works but something is different. Maybe some calcultation that differ.

Yeah, I’ve got my next and previous the wrong way round.

Once again, you may need to fiddle - the example above was mainly to demonstrate the approach I would take to the same problem. However, try:

function page_object_jump( $direction, $steps, $item ) {
	$item = ( ! empty( $item ) ) ? $item : page();
        $siblings = $item->siblings();
        $index = $siblings->indexOf($item);

        if( $direction === 'reverse' ) {
            if( ( $index - $steps ) < 0 ) {
                return $siblings->first();
            }
            return $siblings->nth($index - $steps);
        }
        else if( $direction === 'forward' ) {
            if( ( $index + $steps ) > ( $siblings->count() - 1 ) ) {
                return $siblings->last();
            }
            return $siblings->nth($index + $steps);
        }
	return $item;
}

Yours are probably better when it work. Now it’s quite buggy so I’ll use my own for now.

Sorry to hear it’s buggy. When I get home I’ll try and test it. On my mobile phone at the moment. Honestly thought once I had corrected the + / - mix-up it would work as expected. What’s happening that’s buggy?

I list 4 items with one step forward on each.

I some cases there are unique items on each, witch is correct. Sometimes there are the same items and sometimes some of the items are the same.

If you are going to test it, test at the beginning, the middle and the end. I suspect it might be the edges that don’t work well.

Sorry it’s taken me a while to respond. I’ve just used the function posted above on a fresh installation of the starterkit, and in the project template it seems to be working correctly. For example, when I use the following:

<?php echo page_object_jump("forward", 1, $page)->title(); ?>
<?php echo page_object_jump("forward", 2, $page)->title(); ?>
<?php echo page_object_jump("forward", 3, $page)->title(); ?>
<?php echo page_object_jump("forward", 4, $page)->title(); ?>

From Project A, I get the following output:

Project B
Project C
Project C
Project C

Which is what I would expect. When I try the following:

<?php echo page_object_jump("reverse", 1, $page)->title(); ?>
<?php echo page_object_jump("reverse", 2, $page)->title(); ?>
<?php echo page_object_jump("reverse", 3, $page)->title(); ?>
<?php echo page_object_jump("reverse", 4, $page)->title(); ?>

From Project C I get:

Project B
Project A
Project A
Project A

Also what I would expect.

I may need a code example in order to test this, in that case.

I see! Then our functions work different. Your function jumps until it hit the wall and stop there. My function loops bypass the wall and start over.

The result of my function would be something like this (from Project A):

Project B
Project C
Project A
Project B

From project C:

Project A
Project B
Project C
Project A

Do you see how my function works? It loops, like a slideshow. I think your function is good when the situation needs it. I need the looped solution on my site.

Sitenote: I use this loop as “related” items. The good thing with it is that it will show different related items on every page, without being random.

Ahh, well that’s considerably simpler.

function page_object_jump( $direction, $steps, $item ) {
    $item = ( ! empty( $item ) ) ? $item : page();
    $siblings = ($direction === 'reverse') ? $item->siblings()->flip() : $item->siblings();
    $index = ( $siblings->indexOf($item) + $steps ) % $siblings->count();
    return $siblings->nth($index);
}