Skip to content

Fix for #332: adjacent items for unsorted connections #370

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
239 changes: 137 additions & 102 deletions core/connection-type.php
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ public function get_adjacent( $from, $to, $which ) {
}

/**
* Get the previous, next and parent items, in an ordered connection type.
* Get the previous, next and parent items
*
* @param mixed The current item
*
Expand All @@ -337,106 +337,141 @@ public function get_adjacent_items( $item ) {
'next' => false,
);

$r = $this->direction_from_item( $item );
if ( !$r )
return false;

list( $direction, $item ) = $r;

$connected_series = $this->set_direction( $direction )->get_connected( $item,
array(), 'abstract' )->items;

if ( empty( $connected_series ) )
return $r;

if ( count( $connected_series ) > 1 ) {
trigger_error( 'More than one connected parents found.', E_USER_WARNING );
}

$parent = $connected_series[0];

$result['parent'] = $parent->get_object();
$result['previous'] = $this->get_previous( $item->ID, $parent->ID );
$result['next'] = $this->get_next( $item, $parent );

return $result;
}

/**
* Optimized inner query, after the outer query was executed.
*
* Populates each of the outer querie's $post objects with a 'connected' property, containing a list of connected posts
*
* @param object|array $items WP_Query instance or list of post objects
* @param string|array $extra_qv Additional query vars for the inner query.
* @param string $prop_name The name of the property used to store the list of connected items on each post object.
*/
public function each_connected( $items, $extra_qv = array(), $prop_name = 'connected' ) {
if ( is_a( $items, 'WP_Query' ) )
$items =& $items->posts;

if ( empty( $items ) || !is_object( $items[0] ) )
return;

$post_types = array_unique( wp_list_pluck( $items, 'post_type' ) );

if ( count( $post_types ) > 1 ) {
$extra_qv['post_type'] = 'any';
}

$possible_directions = array();

foreach ( array( 'from', 'to' ) as $direction ) {
$side = $this->side[ $direction ];

if ( 'post' == $side->get_object_type() ) {
foreach ( $post_types as $post_type ) {
if ( $side->recognize_post_type( $post_type ) ) {
$possible_directions[] = $direction;
}
}
}
}

$direction = _p2p_compress_direction( $possible_directions );

if ( !$direction )
return false;

$directed = $this->set_direction( $direction );

// ignore pagination
foreach ( array( 'showposts', 'posts_per_page', 'posts_per_archive_page' ) as $disabled_qv ) {
if ( isset( $extra_qv[ $disabled_qv ] ) ) {
trigger_error( "Can't use '$disabled_qv' in an inner query", E_USER_WARNING );
}
}
$extra_qv['nopaging'] = true;

$q = $directed->get_connected( $items, $extra_qv, 'abstract' );

$raw_connected = array();
foreach ( $q->items as $item )
$raw_connected[] = $item->get_object();

p2p_distribute_connected( $items, $raw_connected, $prop_name );
}

public function get_desc() {
$desc = array();

foreach ( array( 'from', 'to' ) as $key ) {
$desc[ $key ] = $this->side[ $key ]->get_desc();
}

$label = sprintf( '%s %s %s', $desc['from'], $this->strategy->get_arrow(), $desc['to'] );

$title = $this->get_field( 'title', 'from' );

if ( $title )
$label .= " ($title)";

return $label;
}
$r = $this->direction_from_item( $item );
if (!$r )
return;

list( $direction, $item ) = $r;

$connected_series = $this->set_direction( $direction )->get_connected( $item,
array(), 'abstract' )->items;

if ( empty( $connected_series ) )
return $r;

if ( count( $connected_series ) > 1 ) {
trigger_error( 'More than one connected parents found.', E_USER_WARNING );
}

$parent = $connected_series[0];

$result['parent'] = $parent->get_object();

$directed = $this->set_direction( $direction );

$key = $directed->get_orderby_key();
if ( $key )
{
$result['previous'] = $this->get_previous( $item->ID, $parent->ID );
$result['next'] = $this->get_next( $item, $parent );
}
else // connection is unsorted
{
$relatives = $this->get_connected( $result['parent'],
array(), 'abstract' )->items;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will only fetch the first 10 connections, so it will return incorrect results if there are more than 10 items in a series.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahh that sucks, can this be fixed?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could replace array() with array( 'p2p:per_page' => -1 ).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this revision is safe to use right?


// sort it by post_date DESC

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like that you changed the indentation from tabs to spaces. It makes it really hard to see the relevant changes.

$last2 = FALSE;
$last = FALSE;
$current = FALSE;
$i = 0;
$length = count ($relatives);
while ($i < $length AND $last != $item->ID)
{
if ($last) $last2 = $last;
$last = $current;
$current = $relatives[$i]->ID;
$i++;
}
if ($last == $item->ID)
{
if ($last2) $result['previous'] = get_post($last2);
$result['next'] = get_post($current);
}
if ($current == $item->ID)
{
$result['previous'] = get_post($last);
}
}
return $result;
}

/**
* Optimized inner query, after the outer query was executed.
*
* Populates each of the outer querie's $post objects with a 'connected' property, containing a list of connected posts
*
* @param object|array $items WP_Query instance or list of post objects
* @param string|array $extra_qv Additional query vars for the inner query.
* @param string $prop_name The name of the property used to store the list of connected items on each post object.
*/
public function each_connected( $items, $extra_qv = array(), $prop_name = 'connected' ) {
if ( is_a( $items, 'WP_Query' ) )
$items =& $items->posts;

if ( empty( $items ) || !is_object( $items[0] ) )
return;

$post_types = array_unique( wp_list_pluck( $items, 'post_type' ) );

if ( count( $post_types ) > 1 ) {
$extra_qv['post_type'] = 'any';
}

$possible_directions = array();

foreach ( array( 'from', 'to' ) as $direction ) {
$side = $this->side[ $direction ];

if ( 'post' == $side->get_object_type() ) {
foreach ( $post_types as $post_type ) {
if ( $side->recognize_post_type( $post_type ) ) {
$possible_directions[] = $direction;
}
}
}
}

$direction = _p2p_compress_direction( $possible_directions );

if ( !$direction )
return false;

$directed = $this->set_direction( $direction );

// ignore pagination
foreach ( array( 'showposts', 'posts_per_page', 'posts_per_archive_page' ) as $disabled_qv ) {
if ( isset( $extra_qv[ $disabled_qv ] ) ) {
trigger_error( "Can't use '$disabled_qv' in an inner query", E_USER_WARNING );
}
}
$extra_qv['nopaging'] = true;

$q = $directed->get_connected( $items, $extra_qv, 'abstract' );

$raw_connected = array();
foreach ( $q->items as $item )
$raw_connected[] = $item->get_object();

p2p_distribute_connected( $items, $raw_connected, $prop_name );
}

public function get_desc() {
$desc = array();

foreach ( array( 'from', 'to' ) as $key ) {
$desc[ $key ] = $this->side[ $key ]->get_desc();
}

$label = sprintf( '%s %s %s', $desc['from'], $this->strategy->get_arrow(), $desc['to'] );

$title = $this->get_field( 'title', 'from' );

if ( $title )
$label .= " ($title)";

return $label;
}
}