PHPackages                             10up/wp-content-connect - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. 10up/wp-content-connect

ActiveLibrary

10up/wp-content-connect
=======================

WordPress library that enables direct relationships for posts to posts and posts to users.

1.6.0(1y ago)9515.0k↓48.1%23[12 issues](https://github.com/10up/wp-content-connect/issues)[11 PRs](https://github.com/10up/wp-content-connect/pulls)GPL-3.0-or-laterJavaScriptCI passing

Since Mar 14Pushed 3mo ago10 watchersCompare

[ Source](https://github.com/10up/wp-content-connect)[ Packagist](https://packagist.org/packages/10up/wp-content-connect)[ Docs](https://github.com/10up/wp-content-connect)[ RSS](/packages/10up-wp-content-connect/feed)WikiDiscussions develop Synced 1mo ago

READMEChangelog (7)Dependencies (3)Versions (21)Used By (0)

WP Content Connect
==================

[](#wp-content-connect)

> WordPress library that enables direct relationships for posts to posts and posts to users.

[![Support Level](https://camo.githubusercontent.com/570a8b870e3b5e0c1805b8701b5f304aa1cf440e74807b255a4c4339af8df5f1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f737570706f72742d737461626c652d626c75652e737667)](#support-level) [![WordPress tested up to version](https://camo.githubusercontent.com/1f7359ef7da6a4ff041c842afe01d12f427c62c9728893a048ae7cc1fa42dc81/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f576f726450726573732d76362e372532307465737465642d737563636573732e737667)](https://camo.githubusercontent.com/1f7359ef7da6a4ff041c842afe01d12f427c62c9728893a048ae7cc1fa42dc81/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f576f726450726573732d76362e372532307465737465642d737563636573732e737667) [![CodeQL](https://github.com/10up/wp-content-connect/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/10up/wp-content-connect/actions/workflows/github-code-scanning/codeql) [![GPL-3.0-or-later License](https://camo.githubusercontent.com/8451c8782c1244d07e03bf8ca52e1f8ba8889cd418342a8cff48681d5afef340/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f313075702f77702d636f6e74656e742d636f6e6e6563742e737667)](https://github.com/10up/wp-content-connect/blob/master/LICENSE.md)

Installation and Usage
----------------------

[](#installation-and-usage)

WP Content Connect can be used as a plugin or a standalone library. The easiest way to use this is to install as a plugin and activate.

### Composer install

[](#composer-install)

#### As a library

[](#as-a-library)

First, require this repository using the command line:

`$ composer require 10up/wp-content-connect`

or directly in `composer.json`:

```
  "require": {
    "10up/wp-content-connect": "^1.6.0"
  }

```

This will install WP Content Connect to your `vendor` folder and allow you to to use it as a library by calling `\TenUp\ContentConnect\Plugin::instance();` from your code.

#### As a plugin

[](#as-a-plugin)

Alternatively, if you prefer to have composer install it as a plugin, you may redeclare this package in your `composer.json` using the following example:

```
{
  "name": "your project name",
  "repositories": [
    {
      "type": "package",
      "package": {
        "name": "10up/wp-content-connect",
        "type": "wordpress-plugin",
        "version": "1.6.0",
        "source": {
          "url": "https://github.com/10up/wp-content-connect.git",
          "type": "git",
          "reference": "1.6.0"
        }
      }
    }
  ],
  "require": {
    "10up/wp-content-connect": "^1.5",
    "composer/installers": "^1.7"
  },
  "extra": {
    "installer-paths": {
      "plugins/wp-content-connect/": [
        "10up/wp-content-connect"
      ]
    }
  }
}

```

Defining Relationships
----------------------

[](#defining-relationships)

Relationships can be defined once any post types they utilize are defined by hooking into the `tenup-content-connect-init` action. This action is fired on the WordPress `init` action, at priority 100, so any post types must be registered prior to this. Currently supported relationships are post-to-post and post-to-user. Additionally, when registering a relationship, you must specify a `name`. Name enables multiple distinct relationships between the same object types. For instance, you could have a post-to-user relationship for post type `post` with a type of `researchers` to indicate that any user in the "researcher" relationship is a researcher for the post and have another post-to-user relationship defined for post type `post` with a name of `backer` to indicate that any user in the "backer" relationship contributes financially to the post.

### `define_post_to_post( $from, $to, $name, $args = array() )`

[](#define_post_to_post-from-to-name-args--array-)

This method defines a post to post relationship between two post types, `$from` and `$to`.

#### Parameters

[](#parameters)

`$from` (String) First post type in the relationship

`$to` (String|Array) Second post type(s) in the relationship

`$name` (String) Unique name for this relationship, used to distinguish between multiple relationships between the same post types

`$args` (Array) Array of options for the relationship

#### Args

[](#args)

Args expects options for the `from` and `to` sides of the relationship as top level keys. Options for each direction are as follows:

- `enable_ui` (Bool) - Should the default UI be enabled for the current side of this relationship
- `sortable` (Bool) - Should the relationship be sortable for the current side of this relationship
- `labels` (Array) - Labels used in the UI for the relationship. Currently only expects one value, `name` (String)

#### Return Value

[](#return-value)

This method returns an instance of `\TenUp\ContentConnect\Relationships\PostToPost` specific to this relationship. The object can then be used to manage related items manually, if required. See the &lt;@TODO insert link&gt; section below.

Example:

```
function my_define_relationships( $registry ) {
    $args = array(
        'from' => array(
            'enable_ui' => true,
            'sortable' => true,
            'labels' => array(
                'name' => 'Related Tires',
            ),
        ),
        'to' => array(
            'enable_ui' => false,
            'sortable' => false,
            'labels' => array(
                'name' => 'Related Cars',
            ),
        ),
    );

    $relationship = $registry->define_post_to_post( 'car', 'tire', 'car-tires', $args );
}
add_action( 'tenup-content-connect-init', 'my_define_relationships' );
```

### `define_post_to_user( $post_type, $name $args = array() )`

[](#define_post_to_user-post_type-name-args--array-)

This method defines a post to user relationship between the supplied post type and users.

#### Parameters

[](#parameters-1)

`$post_type` (String) The post type to be related to users

`$name` (String) Unique name for this relationship, used to distinguish between multiple relationships between users and the same post type

`$args` (Array) Array of options for the relationship

#### Args

[](#args-1)

Args expects options for the `from` (post type) side of the relationship as a top level key. Options are as follows:

- `enable_ui` (Bool) - Should the default UI be enabled for the current side of this relationship
- `sortable` (Bool) - Should the relationship be sortable for the current side of this relationship
- `labels` (Array) - Labels used in the UI for the relationship. Currently only expects one value, `name` (String)

#### Return Value

[](#return-value-1)

This method returns an instance of `\TenUp\ContentConnect\Relationships\PostToUser` specific to this relationship. The object can then be used to manage related items manually, if required. See the &lt;@TODO insert link&gt; section below.

Example:

```
function my_define_relationships( $registry ) {
    $args = array(
        'from' => array(
            'enable_ui' => true,
            'sortable' => false,
            'labels' => array(
                'name' => 'Related Users',
            ),
        ),
    )

    $relationship = $registry->define_post_to_user( 'post', 'related', $args );
}
add_action( 'tenup-content-connect-init', 'my_define_relationships' );
```

*There is not currently support for rendering any default UIs on the User side of these relationships*

### Sortable Relationships

[](#sortable-relationships)

Relationships can optionally support sortable related items. Order can be stored independently for both sides of a relationship. For example, if you have cars and tires, you may have a car that has 5 related tires, and if you wanted to sort the tires, you do so from the car page. You could then go to one of the related tires, and order all of the cars it is related to separately.

Since you can manage this relationship from both post types in the relationship, if you added a tire from the car page, and you had relationship data previously stored on the tire, the NEW car in the relationship will still show up in query results, at the very end (after all of your other pre-ordered data).

Query Integration
-----------------

[](#query-integration)

Querying for relationships is enabled via a new `relationship_query` parameter for `WP_Query`. The format for `relationship_query` is very similar to `tax_query`.

A valid relationship query segment **requires** `name` and either `related_to_post` OR `related_to_user`. As many relationship segments as necessary can be combined to create a specific set of results, and can be combined using an `AND` or `OR` relation.

#### Top Level Args

[](#top-level-args)

- `relation` (String) Can be either `AND` (default) or `OR`. How all of the segments in the relationship should be combined.

#### Segment Args

[](#segment-args)

- `name` (String) The unique name for the relationship you are querying. Should match a `name` from registering relationships.
- `related_to_post` (Int) Find items in the relationship related to this post ID. Cannot be used in the same segment as `related_to_user`.
- `related_to_user` (Int) Find items in the relationship related to this user ID. Cannot be used in the same segment as `related_to_post`.

Example:

```
$query = new WP_Query( array(
    'post_type' => 'post',
    'relationship_query' => array(
        'relation' => 'AND', // AND is default
        array(
            'related_to_post' => 25,
            'name' => 'related',
        ),
        array(
            'related_to_user' => 5,
            'name' => 'researcher',
        )
    ),
) );
```

Currently, querying for multiple post types in WP\_Query may not work as expected. When using relationship queries, make sure to only have one `post_type` value in WP\_Query.

#### Order By

[](#order-by)

For relationships where sorting is disabled, all of the default WP\_Query `orderby` options are supported. In addition to default `orderby` options, if sorting is enabled for a relationship, an additional orderby parameter `relationship` is supported. When using `relationship` as the orderby value, the order is always `ASC` and you must adhere to the following `WP_Query` and `WP_User_Query` restrictions:

- Compound relationship queries are not allowed - only one segment may be added to the query

For example, this is fine:

```
'relationship_query' => array(
    array(
        'related_to_post' => 25,
        'name' => 'related',
    ),
),
'orderby' => 'relationship',
```

while this will not work (orderby will be ignored):

```
'relationship_query' => array(
    array(
        'related_to_post' => 25,
        'name' => 'related',
    ),
    array(
		'related_to_post' => 15,
		'name' => 'related',
	),
),
'orderby' => 'relationship',
```

Manually Managing Relationships
-------------------------------

[](#manually-managing-relationships)

If you choose to not use the built in UIs for relationships, you'll need to manually update relationships. **DO NOT** try and work directly with the database tables. Instead, work with the following API methods. The underlying implementations may need to change from time to time, but the following methods should continue to function if the underlying implementations need to change.

These methods are available on the relationship objects returned when defining the relationship. Make sure to call these methods on the specific relationship object you are defining a relationship for, as these methods are specific to the relationship context (they are aware of the `name` of the relationship, as well as the post types in the relationship).

If you don't already have a relationship object, you can get one from the registry using either `Registry->get_post_to_post_relationship()` or `Registry->get_post_to_user_relationship()`.

### `Registry->get_post_to_post_relationship( $cpt1, $cpt2, $name )`

[](#registry-get_post_to_post_relationship-cpt1-cpt2-name-)

Returns the relationship object between the two post types with the provided name.

#### Parameters

[](#parameters-2)

`$cpt1` (String) The first post type in the relationship

`$cpt2` (String) The second post type in the relationship

`$name` (String) The name of the relationship, as passed to define\_post\_to\_post\_relationship

#### Example

[](#example)

```
$registry = \TenUp\ContentConnect\Plugin::instance()->get_registry();

// Gets the car to tire relationship defined in the example above
$relationship = $registry->get_post_to_post_relationship( 'car', 'tire', 'car-tires' );
```

### `Registry->get_post_to_user_relationship( $post_type, $name )`

[](#registry-get_post_to_user_relationship-post_type-name-)

Returns the relationship object between the post types and users with the provided name.

#### Parameters

[](#parameters-3)

`$post_type` (String) The post type in the post to user relationship

`$name` (String) The name of the relationship, as passed to define\_post\_to\_user\_relationship

#### Example

[](#example-1)

```
$registry = \TenUp\ContentConnect\Plugin::instance()->get_registry();

// Gets the post to user relationship defined in the example above
$relationship = $registry->get_post_to_user_relationship( 'post', 'related' );
```

### `PostToPost->add_relationship( $pid1, $pid2 )`

[](#posttopost-add_relationship-pid1-pid2-)

This method adds a relationship between one post and another, in a post to post relationship. When calling this method, the order of IDs passed is not important.

#### Parameters

[](#parameters-4)

`$pid1` (Int) The ID of the first post in the relationship

`$pid2` (Int) The ID of the second post in the relationship

#### Example

[](#example-2)

```
// $relationship is the return value from ->define_post_to_post()
$relationship->add_relationship( 1, 2 ); // Adds a relationship between post ID 1 and post ID 2
```

### `PostToPost->delete_relationship( $pid1, $pid2 )`

[](#posttopost-delete_relationship-pid1-pid2-)

This methods deletes a relationship between one post and another, in a post to post relationship. When calling this method, the order of IDs passed is not important.

#### Parameters

[](#parameters-5)

`$pid1` (Int) The ID of the first post in the relationship. Does **not** need to be in the same order as the relationship was added.

`$pid2` (Int) The ID of the second post in the relationship. Does **not** need to be in the same order as the relationship was added.

#### Example

[](#example-3)

```
// $relationship is the return value from ->define_post_to_post()
// Note that the example above added these in the reverse order, but the relationship is still deleted
$relationship->delete_relationship( 2, 1 ); // Deletes the relationship between post ID 1 and post ID 2.
```

### `PostToPost->replace_relationships( $post_id, $related_ids )`

[](#posttopost-replace_relationships-post_id-related_ids-)

Replaces existing relationships for the post to post relationship. Any relationship that is present in the database but not in $related\_ids will no longer be related.

#### Parameters

[](#parameters-6)

`$post_id` (Int) The ID of the post we are replacing relationships from.

`$related_ids` (Array) An array of Post IDs of items related to $post\_id

#### Example

[](#example-4)

Post ID 5 is related to posts 2, 3, 6, 7, 8

```
// $relationship is the return value from ->define_post_to_post()
$relationship->replace_relationships( 5, array( 2, 3, 6, 7, 8 ) );
```

### `PostToPost->save_sort_data( $object_id, $ordered_ids )`

[](#posttopost-save_sort_data-object_id-ordered_ids-)

For a relationship with sorting enabled, this saves the order of the posts for a single direction of the relationship.

#### Parameters

[](#parameters-7)

`$object_id` (Int) The Post ID that we are ordering from. If we were ordering 5 tires for a single car, this would be the car ID.

`$ordered_ids` (Array) An array of Post IDs, in the order they should be sorted. If we were ordering 5 tires for a single car, this is the ordered tire IDs.

#### Example

[](#example-5)

Car ID 5 has five related tires, that should be ordered 7, 6, 3, 8, 2

```
// $relationship is the return value from ->define_post_to_post()
$relationship->save_sort_data( 5, array( 7, 6, 3, 8, 2 ) );
```

### `PostToUser->add_relationship( $post_id, $user_id )`

[](#posttouser-add_relationship-post_id-user_id-)

This method adds a relationship between a post and a user, in a post to user relationship.

#### Parameters

[](#parameters-8)

`$post_id` (Int) The ID of the post in the relationship

`$user_id` (Int) The ID of the user in the relationship

#### Example

[](#example-6)

```
// $relationship is the return value from ->define_post_to_user()
$relationship->add_relationship( 1, 5 ); // Adds a relationship between post 1 and user 5
```

### `PostToUser->delete_relationship( $post_id, $user_id )`

[](#posttouser-delete_relationship-post_id-user_id-)

This method deletes a relationship between a post and a user, in a post to user relationship.

#### Parameters

[](#parameters-9)

`$post_id` (Int) The ID of the post in the relationship

`$user_id` (Int) The ID of the user in the relationship

#### Example

[](#example-7)

```
// $relationship is the return value from ->define_post_to_user()
$relationship->delete_relationship( 1, 5 ); // Deletes the relationship between post 1 and user 5
```

### `PostToUser->replace_post_to_user_relationships( $post_id, $user_ids )`

[](#posttouser-replace_post_to_user_relationships-post_id-user_ids-)

Replaces users related to a post with the provided set of user ids. Any users related to the post that are not provided in $user\_ids will no longer be related.

#### Parameters

[](#parameters-10)

`$post_id` (Int) The ID of the post we are replacing relationships from.

`$user_ids` (Array) An array of User IDs related to $post\_id

#### Example

[](#example-8)

Post ID 5 is related to users 3, 4, 5

```
// $relationship is the return value from ->define_post_to_user()
$relationship->replace_post_to_user_relationships( 5, array( 3, 4, 5 ) );
```

### `PostToUser->replace_user_to_post_relationships( $user_id, $post_ids )`

[](#posttouser-replace_user_to_post_relationships-user_id-post_ids-)

Replaces posts related to a user with the provided set of post ids. Any posts related to the user that are not provided in $post\_ids will no longer be related.

#### Parameters

[](#parameters-11)

`$user_id` (Int) The User ID we are replacing relationships from.

`$post_ids` (Array) An array of Post IDs related to $user\_id

#### Example

[](#example-9)

User 2 is related to posts 6, 7, 8

```
// $relationship is the return value from ->define_post_to_user()
$relationship->replace_user_to_post_relationships( 2, array( 6, 7, 8 ) );
```

### `PostToUser->save_post_to_user_sort_data( $object_id, $ordered_user_ids )`

[](#posttouser-save_post_to_user_sort_data-object_id-ordered_user_ids-)

For a relationship with sorting enabled, this saves the order of users for a particular post

#### Parameters

[](#parameters-12)

`$object_id` (Int) The ID of the post to store the order of users for

`$ordered_user_ids` (Array) Array of User IDs, in the order they should be sorted.

#### Example

[](#example-10)

Post ID has 5 users that need to be stored in the following order: 2, 4, 1, 6, 3

```
// $relationship is the return value from ->define_post_to_user()
$relationship->save_post_to_user_sort_data( 5, array( 2, 4, 1, 6, 3 ) );
```

### `PostToUser->save_user_to_post_sort_data( $user_id, $ordered_post_ids )`

[](#posttouser-save_user_to_post_sort_data-user_id-ordered_post_ids-)

For a relationship with sorting enabled, this saves the order of posts for a particular user

#### Parameters

[](#parameters-13)

`$user_id` (Int) The ID of the user to store the order of posts for

`$ordered_post_ids` (Array) Array of Post IDs, in the order they should be sorted

#### Example

[](#example-11)

User ID 1 has 5 posts that need to be stored in the following order: 4, 2, 7, 9, 8

```
// $relationship is the return value from ->define_post_to_user()
$relationship->save_user_to_post_sort_data( 1, array( 4, 2, 7, 9, 8 ) );
```

Support Level
-------------

[](#support-level)

**Stable:** 10up is not planning to develop any new features for this, but will still respond to bug reports and security concerns. We welcome PRs, but any that include new features should be small and easy to integrate and should not include breaking changes. We otherwise intend to keep this tested up to the most recent version of WordPress.

Changelog
---------

[](#changelog)

A complete listing of all notable changes to WP Content Connect are documented in [CHANGELOG.md](https://github.com/10up/wp-content-connect/blob/develop/CHANGELOG.md).

Contributing
------------

[](#contributing)

Please read [CODE\_OF\_CONDUCT.md](https://github.com/10up/wp-content-connect/blob/develop/CODE_OF_CONDUCT.md) for details on our code of conduct, [CONTRIBUTING.md](https://github.com/10up/wp-content-connect/blob/develop/CONTRIBUTING.md) for details on the process for submitting pull requests to us, and [CREDITS.md](https://github.com/10up/wp-content-connect/blob/develop/CREDITS.md) for a listing of maintainers of, contributors to, and libraries used by WP Content Connect.

Like what you see?
------------------

[](#like-what-you-see)

[![](https://camo.githubusercontent.com/5ec5223fa6fe20a5ca00d8d768bd7ee91e93f67c9d7a06e575c87e3ed1d00263/68747470733a2f2f313075702e636f6d2f75706c6f6164732f323031362f31302f313075702d4769746875622d42616e6e65722e706e67)](http://10up.com/contact/)

###  Health Score

53

—

FairBetter than 97% of packages

Maintenance61

Regular maintenance activity

Popularity42

Moderate usage in the ecosystem

Community24

Small or concentrated contributor base

Maturity72

Established project with proven stability

 Bus Factor1

Top contributor holds 57.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~360 days

Recently: every ~625 days

Total

9

Last Release

108d ago

Major Versions

1.7.0-beta.1 → 2.0.0-beta.22026-01-30

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/3358927?v=4)[10up](/maintainers/10up)[@10up](https://github.com/10up)

---

Top Contributors

[![cmmarslender](https://avatars.githubusercontent.com/u/1915905?v=4)](https://github.com/cmmarslender "cmmarslender (152 commits)")[![jeffpaul](https://avatars.githubusercontent.com/u/2818133?v=4)](https://github.com/jeffpaul "jeffpaul (58 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (25 commits)")[![s3rgiosan](https://avatars.githubusercontent.com/u/499982?v=4)](https://github.com/s3rgiosan "s3rgiosan (21 commits)")[![moraleida](https://avatars.githubusercontent.com/u/1174547?v=4)](https://github.com/moraleida "moraleida (2 commits)")[![petenelson](https://avatars.githubusercontent.com/u/1757075?v=4)](https://github.com/petenelson "petenelson (2 commits)")[![mmcachran](https://avatars.githubusercontent.com/u/375068?v=4)](https://github.com/mmcachran "mmcachran (1 commits)")[![dinhtungdu](https://avatars.githubusercontent.com/u/5423135?v=4)](https://github.com/dinhtungdu "dinhtungdu (1 commits)")[![kirtangajjar](https://avatars.githubusercontent.com/u/8456197?v=4)](https://github.com/kirtangajjar "kirtangajjar (1 commits)")[![alexisbellido](https://avatars.githubusercontent.com/u/305270?v=4)](https://github.com/alexisbellido "alexisbellido (1 commits)")[![mphillips](https://avatars.githubusercontent.com/u/18812?v=4)](https://github.com/mphillips "mphillips (1 commits)")[![pcrumm](https://avatars.githubusercontent.com/u/40171?v=4)](https://github.com/pcrumm "pcrumm (1 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/10up-wp-content-connect/health.svg)

```
[![Health](https://phpackages.com/badges/10up-wp-content-connect/health.svg)](https://phpackages.com/packages/10up-wp-content-connect)
```

###  Alternatives

[elgg/elgg

Elgg is an award-winning social networking engine, delivering the building blocks that enable businesses, schools, universities and associations to create their own fully-featured social networks and applications.

1.7k15.7k5](/packages/elgg-elgg)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

44643.1k1](/packages/pressbooks-pressbooks)[johnbillion/user-switching

Instant switching between user accounts in WordPress and WooCommerce.

19768.3k2](/packages/johnbillion-user-switching)[rainlab/blog-plugin

Blog plugin for October CMS

17257.7k](/packages/rainlab-blog-plugin)[rainlab/user-plugin

User plugin for October CMS

11954.3k13](/packages/rainlab-user-plugin)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
