Posts 2 Posts

Posts 2 Posts: Version 1.6

There were some improvements commited to the development version of the plugin for a while and I thought I’d do a quick release, to get them in the hands of users.

With version 1.6, P2P development will effectively be entering hibernation mode. I won’t be working on any new features or bug fixes, since the plugin already works well enough on the single site where I use it. Also, I won’t be answering support questions anymore; sorry.

Of course, I’d be happy to review and merge pull requests that people open and still hope that I’ll eventually be able to hand it off to someone else.

Posts 2 Posts: Version 1.4

Improved UI

When you need to create connections, there’s now a link that reveals the connection candidates. This saves vertical space when you’re doing something else in the post editing screen.

When you found the item you want to connect to, you can now click anywhere in the row, instead of just on the ‘+’ icon. This makes it both easier to target and less confusing. After the connection is created, you can click on the connected post’s title to edit it, as before.

Revamped connection querying

The SQL generated for querying connections is now more precise, so that trashed and auto-draft posts are ignored by default.

Also, you can now filter both ends of the connection. For example, you can find all pages connected to any posts in the ‘Tutorials’ category:

$pages = new WP_Query( array(
  'post_type' => 'page',
  'connected_type' => 'pages_to_posts',
  'connected_to' => 'any',
  'connected_query' => array(
    'category_name' => 'tutorials',
  ),
  'nopaging' => true
) );

The arguments in the ‘connected_query’ array are used to restrict the other end of the connection. All normal arguments for WP_Query – and for WP_User_Query, respectively – are supported.

New Hooks

Squashed Bugs

As with every release, there are numerous little things that get fixed along the way, which can be seen here.

Posts 2 Posts: Version 1.3

Improved API

In this release, I focused on making the API more uniform; everything works for both posts-to-posts and posts-to-users connections now. This is possible because you can pass whole post and user objects, instead of just IDs.

Previously:

$connected = get_users( array(
	'connected_type' => 'posts_to_users',
	'connected_items' => $post->ID
) );

Now:

$connected = get_users( array(
	'connected_type' => 'posts_to_users',
	'connected_items' => $post
) );

This small change gives P2P more information to work with, which means fewer database queries are needed.

Shortcodes!

The plugin now comes with a pair of shortcodes for conveniently listing connected items anywhere.

Say you defined a connection type called ‘posts_to_pages’. Here’s how the shortcode would look like:

[p2p_connected type=posts_to_pages]

If you insert that into a post, it will display a list of connected pages. If you insert it into a page, it will display a list of connected posts.

And there’s one for related posts too:

[p2p_related type=posts_to_pages]

Shortcodes and widgets also have filters for modifying the HTML output.

Default field values

You can now set default values for the connection fields in the metabox, likes so:

p2p_register_connection_type( array(
	'name' => 'posts_to_pages',
	'from' => 'post',
	'to' => 'page',
 
	'fields' => array(
		'color' => array(
			'title' => 'Color',
			'type' => 'checkbox',
			'values' => array( 'green', 'yellow', 'blue', 'white' ),
			'default' => 'blue'
		),
	)
) );

In total, there were 16 resolved issues in this release.

Posts 2 Posts: Version 1.2

The main attraction in this release is the new admin screen that gives an overview of all the connection types found in the system:

Connection Types screen

Another thing to note is that queries like this no longer work:

$query = new WP_Query( array(
  'connected_items' => get_queried_object_id()
) );

You have to set the ‘connected_type’ parameter:

$query = new WP_Query( array(
  'connected_type' => 'posts_to_pages',
  'connected_items' => get_queried_object_id()
) );

Also, you can pass an array of connection types and P2P will pick the ones that make sense.

$query = new WP_Query( array(
  'connected_type' => array( 'posts_to_pages', 'actors_to_movies' ),
  'connected_items' => get_queried_object_id()
) );

As with every release, it contains a bunch of smaller enhancements and bug fixes. See the changelog for more details.

Posts 2 Posts: Version 1.1

I’m pleased to announce that the Posts 2 Posts plugin now also supports posts-to-users connections. (It supports users-to-users connections as well, but there’s no UI for them).

This is made possible by a new p2p_type column on the wp_p2p table, with which we can clearly distinguish between user ids and post ids. If you’re upgrading from a previous version of Posts 2 Posts, all the existing connections will be automatically updated to have the correct value for this column.

For the next version, I’m thinking of supporting connections between posts on different blogs in a multisite network.

Posts 2 Posts: Version 1.0

It’s been a year and a half since the initial 0.1 release. Posts 2 Posts has come a long way since then and it’s been a very interesting journey.

Here’s what’s new in version 1.0:

Indeterminate connection types

Initially, connection types were organised exclusively around post types. Since version 0.9.5, you can use arbitrary query variables to define the sides of a connection type.

And with this release, there’s a clear distinction between regular connection types and indeterminate connection types, which are a lot easier to control now.

Improved support for ordered connections

You can now order connections both ways. Also, you can get the previous and next post in the list. See Connection ordering.

If you have actors and movies, it’s a lot easier now to get other actors that have played in the same movies as a particular actor. See the wiki page about related posts.

Additionally, you can show related posts using the widget.

More connection field types

In previous versions, a connection field could be either a text input or a dropdown. Now, you can also add radio buttons, checkboxes and textareas. See Connection information.

You can see all the tickets closed for this release on github:

https://github.com/scribu/wp-posts-to-posts/issues?milestone=2&state=closed

Posts 2 Posts: Version 0.9.5

In short, this version improves the connection type based API introduced in 0.9 and removes the old API.

Connection Type IDs

Previously, you had to keep track of connection type instances yourself, making it hard to work with more than one connection type.

Old:

global $my_connection_type;

$my_connection_type = p2p_register_connection_type( array(
	'from' => 'post',
	'to' => 'page'
) );

New:

p2p_register_connection_type( array(
	'id' => 'posts_to_pages',
	'from' => 'post',
	'to' => 'page'
) );

And, to get a list of connected items, instead of:

global $my_connection_type;

$connected = $my_connection_type->get_connected( get_queried_object_id() );

you can now do it in one line:

$connected = p2p_type( 'posts_to_pages' )->get_connected( get_queried_object_id() );

One-To-Many Connections

There’s a new ‘cardinality’ argument:

p2p_register_connection_type( array(
  'from' => 'post',
  'to' => 'page',
  'cardinality' => 'one-to-many',
  'reciprocal' => true
) );

When editing a page, you will only be able to connect it to a single post and only to a post that doesn’t have a connected page yet.

'cardinality' => 'many-to-one' has the same effect, in reverse.

Arbitrary query variables

You can now distinguish between connection types based on any query variable, not just ‘post_type’:

$types = array(
    'bug' => 'Bug',
    'feature' => 'Feature'
);

foreach ( $types as $type => $title ) {
    p2p_register_connection_type( array(
        'from' => 'contact',
        'to' => 'ticket',
        'to_query_vars' => array(
            'meta_key' => 'type',
            'meta_value' => $type
        ),
        'title' => array( 'from' => $title ),
    );
}

The above code will create two meta boxes: in one, contacts will only be able to create connections to ‘bug’-type tickets and in the other only to ‘feature’-type tickets.

There’s a matching ‘from_query_vars’ argument as well, so you could, for example, create a connection type between posts from category X to posts with tag Y etc.

Removed old API

I went ahead and removed the old API. Here’s the migration path:

Old New
p2p_connect() p2p_type( ‘my_connection_type’ )->connect()
p2p_disconnect() p2p_type( ‘my_connection_type’ )->disconnect()
p2p_get_connected() p2p_type( ‘my_connection_type’ )->get_connected()

The benefit, of course, is that each of the new methods enforces the rules establised when registering the connection type.

Finally, I set up a code reference site, just to play around with DocBlox. Let me know if you find it useful.

Posts 2 Posts: Version 0.9

Admin Box Enhancements

admin box

In the above screenshot you can see the following new features:

Multiple Connections Per Post Type

Besides the ‘fields’ parameter, there’s also a ‘data’ parameter. This can be used to distinguish between connection types:

p2p_register_connection_type( array(
	'from' => 'actor',
	'to' => 'actor',
	'reciprocal' => true,
	'title' => array( 'from' => 'Doubles', 'to' => 'Main Actor' ),
	'data' => array( 'type' => 'doubles' ),
) );

p2p_register_connection_type( array(
	'from' => 'actor',
	'to' => 'actor',
	'reciprocal' => true,
	'title' => 'Friends with',
	'data' => array( 'type' => 'friends' )
) );

API Overhaul

Should I use ‘connected_to’ or ‘connected_from’? Erm… I’ll just use ‘connected’.

Even I was tired of having to think about it. No more.

In previous versions, connection types were tightly coupled with the admin box code. I extracted all the logic into a P2P_Connection_Type class, which should make querying for posts a lot easier.

The old way of doing things still works, except in the following cases:

Old:

$my_query = new WP_Query( array(
    'ignore_sticky_posts' => true,
    'post_type' => 'artist',
    'each_connected' => array(
        'post_type' => 'art',
    )
) );

New:

$my_query = new WP_Query( array(
    'ignore_sticky_posts' => true,
    'post_type' => 'artist',
) );

$my_connection_type->each_connected( $my_query );

All the tutorials on the wiki have been updated to use the hot new API, so feel free to dig in. :)

Posts 2 Posts: Version 0.8

UI Changes

With the WP 3.2 admin refresh, the connection box UI also received an overhaul:

A significant enhancement in this version is the ability to create draft posts from the connection box. The idea is to be able to make the connections first and then write the content. Hat tip to Oren Kolker.

Additionally, when a post is not published, you will see it’s status. Props Michael Fields for the suggestion.

API Changes

p2p_each_connected() has been revamped to, hopefully, make it easier to use. There’s a detailed tutorial on the wiki:

http://github.com/scribu/wp-posts-to-posts/wiki/Looping-The-Loop

Also, there’s a new function called p2p_list_posts() which takes a WP_Query object or an array of posts as the first argument and outputs a simple unordered list of links to those posts.

Finally, there are 3 new query vars that can be used to get connected posts ordered by a particular connection field. More details on the wiki:

http://github.com/scribu/wp-posts-to-posts/wiki/Connection-ordering

Posts 2 Posts: Version 0.7

As promised, this version comes with a much sexier metabox for managing connections:

Now you can:

It comes with an enhanced API to boot:

Connection information

Storing arbitrary data related to a particular connection has been possible since version 0.4, but being able to edit that data through the UI was far from easy.

So, this release brings a simple way to do that, with a new argument called ‘fields’:

p2p_register_connection_type( array(
	'from' => 'actor',
	'to' => 'movie',

	'fields' => array(
		'role' => 'Role',
		'role_type' => 'Role Type'
	),
	'context' => 'advanced'
) );

Here we just defined a connection type between actors and movies, with each connection having two additional fields: ‘role’ – the role of the actor in that particular movie and ‘role type’.

Duplicates

If you want to enable more than one connection between the same two posts, set 'prevent_duplicates' => false when registering the connection type:

p2p_register_connection_type( array(
	'from' => 'actor',
	'to' => 'movie',
	'fields' => array(
		'role' => 'Role',
		'role_type' => 'Role Type'
	),
	'context' => 'advanced',

	'prevent_duplicates' => false
) );

This will allow you to have actors with two or more different roles in the same movie, for example.

Distinct titles

Finally, for reciprocal connections, you can set different titles for the metabox, depending on which screen you’re on:

p2p_register_connection_type( array(
	'from' => 'actor',
	'to' => 'movie',
	'fields' => array(
		'role' => 'Role',
		'role_type' => 'Role Type'
	),
	'context' => 'advanced',
	'prevent_duplicates' => false,
	'reciprocal' => true,

	'title' => array(
		'from' => 'Played In',
		'to' => 'Cast'
	)
) );

With all those settings in place, you get something like this:

Acknowledgements

Special thanks to ciobi for helping with the UI awesomeness.

Thanks to Alexey Egorov for the icons.

Posts 2 Posts: Version 0.6

Nested Queries

If, for each post in a loop, you find yourself doing a subquery using the ‘connected’ query vars, I’ve got good news for you.

Replace something like this:

while ( have_posts() ) : the_post();
	$connected_writers = get_posts( array(
		'post_type' => 'writer',
		'nopaging' => true,
		'connected_to' => $post->ID,
		'suppress_filters' => false
	) );

	foreach ( $connected_writers as $writer ) {
		echo $writer->post_title;
	}
endwhile;

with this:

p2p_each_connected( 'to', 'writers', array(
	'post_type' => 'writer',
	'nopaging' => true,
) );

while ( have_posts() ) : the_post();
	foreach ( $post->connected_writers as $writer ) {
		echo $writer->post_title;
	}
endwhile;

Notice how each $post now has a connected_writers propery, which is an array containing the connected posts.

The main advantage of this method is that it reduces the number of SQL queries dramatically.

Here’s the original forum thread that spurred this feature.

Several bug fixes also went into this release:

In the next version, I will be focusing on improving the default admin UI.

Posts 2 Posts: Version 0.5

This release is focused on enhancing the API, making it easier to leverage the p2pmeta table.

First of all, a new variable for WP_Query is now available: connected_meta. It allows you to restrict connections based on what meta data they have. Here’s an example:

$my_query = new WP_Query( array(
    'post_type' => 'book',
    'connected_to' => 'any',
    'connected_meta' => array(
        'connection_date' => 'long ago',
    )
) );

This will retrieve any book that has a connection to any other post. Also, the connections have to have a custom field with the key connection_date and the value long ago.

And, if that’s not enough, you can use the advanced meta query syntax:

$my_query = new WP_Query( array(
    'post_type' => 'book',
    'connected_to' => 'any'
    'connected_meta' => array(
        array(
            'key' => 'connection_date',
            'value' => array( 'long ago', 'yesterday' ),
            'compare' => 'IN'
        )
    )
) );

Also, after you do the query, you can access the rest of the connection meta data via the p2p_id property, assigned to each found post:

while ( $my_query->have_posts() ) : $my_query->the_post();

    $connection_type = p2p_get_meta( $post->p2p_id, 'connection_type', true );

endwhile;

Posts 2 Posts: Version 0.4

Using a taxonomy to store post-to-post connections was an interesting exercise. It worked, but when it came time to extend it, it felled flat on its face.

That’s why connections are now stored in a custom table, with an additional meta table for adding arbitrary information per connection.

It is now possible to connect the same two posts twice, but with different metadata, something that would be needed in Justin Tadlock’s movies scenario, for example.

The procedure for migrating old connections is the same as in the previous version: go to /wp-admin/?migrate_p2p and you’re done. (Make sure you have a recent database backup before you do this.)

When searching for posts to connect, it will search only by post title and not by content, as in previous versions.

Reciprocal connections are now stored only once.

Speaking of reciprocal connections, most function in the API accepted a the third parameter, which used to be $reciprocal = false. It has been replaced with $data = array(). More info can be found in the file api.php.

Unless you’re doing advanced stuff, you shouldn’t need to touch the API, though. You can just use WP_Query or get_posts():

Get posts connected from a particular post: $post_id -> $posts

$connected = get_posts( array(
  'suppress_filters' => false,
  'post_type' => 'book',
  'connected_from' => $post_id,
) );

Get posts connected to a particular post: $post_id <- $posts

$connected = get_posts( array(
  'suppress_filters' => false,
  'post_type' => 'book',
  'connected_to' => $post_id,
) );

Get connected posts, regardless of direction: $post_id <- $posts OR $post_id -> $posts

$connected = get_posts( array(
  'suppress_filters' => false,
  'post_type' => 'book',
  'connected' => $post_id,
) );

Posts 2 Posts: Version 0.3

There was an interesting discussion on wp-hackers about how best to store many-to-many relationships between posts.

The conclusion was that custom fields are probably the worst solution. While creating a custom table is the most straightforward way to do it, using a custom taxonomy has the most benefits. The most important one is that, when done right, no hand-written SQL is required.

So, this version of the plugin uses a hidden taxonomy to store the connections between posts.

If you were using an older version of the plugin, go to /wp-admin/?migrate_p2p to migrate your connections. You should probably make a database backup beforehand, just in case.

Besides that, the parameter order for p2p_get_connected() and p2p_list_connected() were changed. See all the API changes.

Posts 2 Posts: Version 0.2

You now have the ability to create multiple connections of the same type from the admin. This was the most requested feature and you should thank Patrik Bóna for providing the initial implementation.

the new metabox

The API functions have also changed (and are now documented), so you might want to take another look at them. I’ve also added a new helper function called p2p_list_connected().

Posts 2 Posts: Version 0.1

With custom post types coming to WordPress 3.0, a feature that’s needed on complex sites is the ability to create relationships between posts of different types.

For example, if you have a ‘review’ post type, you’ll probably want to be able to link it to an ‘event’ post type. Once you register this connection type, you will see a dropdown of events on the review editing screen. (The dropdown will likely be replaced with something more scalable in a future version.)

You can manage and retrieve connections using the provided API functions.

The plugin does not create any new database tables; the connections are stored in the postmeta table.

Version 0.1 is a developer preview release. It’s not meant for casual users.