Version Description
- various bug fixes
- added 'inline' mode for shortcodes
- replaced 'trash' icon with 'minus' icon
- pass direction to 'default_cb'
Download this release
Release Info
Developer | scribu |
Plugin | Posts 2 Posts |
Version | 1.4.3 |
Comparing to | |
See all releases |
Code changes from version 1.4.2 to 1.4.3
- CONTRIBUTING.md +38 -0
- admin/box-factory.php +5 -4
- admin/box.css +2 -2
- admin/box.php +9 -0
- admin/column-factory.php +3 -3
- admin/column.php +5 -5
- admin/factory.php +16 -23
- admin/images/delete.png +0 -0
- admin/images/minus.png +0 -0
- admin/images/{add.png → plus.png} +0 -0
- admin/templates/connection-types-form.html +1 -1
- command.php +110 -0
- core/api.php +8 -1
- core/directed-type.php +48 -45
- core/extra.php +20 -7
- core/indeterminate-type.php +7 -3
- core/item.php +18 -0
- core/list.php +1 -1
- core/query.php +1 -1
- core/side.php +77 -69
- core/storage.php +1 -1
- core/type-factory.php +59 -31
- core/type.php +110 -63
- core/url-query.php +1 -1
- core/util.php +15 -0
- debug-utils.php +40 -0
- lang/posts-to-posts-nl_NL.mo +0 -0
- lang/posts-to-posts-nl_NL.po +65 -69
- posts-to-posts.php +2 -2
- readme.txt +9 -3
- screenshot-1.png +0 -0
- screenshot-2.png +0 -0
- screenshot-3.png +0 -0
- screenshot-4.png +0 -0
- screenshot-5.png +0 -0
CONTRIBUTING.md
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
This guide is meant for developers wanting to work on the plugin code.
|
2 |
+
|
3 |
+
### Setup
|
4 |
+
|
5 |
+
Make a fork and clone it:
|
6 |
+
|
7 |
+
```
|
8 |
+
git clone --recurse-submodules git@github.com:{YOUR GITHUB USERNAME}/wp-posts-to-posts.git posts-to-posts
|
9 |
+
```
|
10 |
+
|
11 |
+
You can now work on the PHP and CSS files.
|
12 |
+
|
13 |
+
### JavaScript
|
14 |
+
|
15 |
+
Don't modify `admin/box.js` directly. Instead:
|
16 |
+
|
17 |
+
- [Install node.js](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager).
|
18 |
+
|
19 |
+
- Install [CoffeeScript](http://coffeescript.org):
|
20 |
+
|
21 |
+
```
|
22 |
+
npm install -g coffee-script
|
23 |
+
```
|
24 |
+
|
25 |
+
and edit the `admin/box.coffee` file. To compile it, run:
|
26 |
+
|
27 |
+
```
|
28 |
+
coffee -c admin
|
29 |
+
```
|
30 |
+
|
31 |
+
### Testing
|
32 |
+
|
33 |
+
The plugin comes with a few unit tests.
|
34 |
+
|
35 |
+
1. Install [PHPUnit](https://github.com/sebastianbergmann/phpunit/).
|
36 |
+
2. Create `tests/wp-tests-config.php` file. ([sample](https://unit-tests.svn.wordpress.org/trunk/wp-tests-config-sample.php))
|
37 |
+
3. [Install the scbFramework](https://github.com/scribu/wp-scb-framework/wiki) in the mu-plugins dir.
|
38 |
+
4. Run `./bin/test`
|
admin/box-factory.php
CHANGED
@@ -5,14 +5,14 @@ define( 'P2P_BOX_NONCE', 'p2p-box' );
|
|
5 |
class P2P_Box_Factory extends P2P_Factory {
|
6 |
|
7 |
function __construct() {
|
8 |
-
|
9 |
|
10 |
add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
|
11 |
add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
|
12 |
add_action( 'wp_ajax_p2p_box', array( $this, 'wp_ajax_p2p_box' ) );
|
13 |
}
|
14 |
|
15 |
-
function filter_ctypes( $args ) {
|
16 |
if ( isset( $args['admin_box'] ) ) {
|
17 |
$box_args = _p2p_pluck( $args, 'admin_box' );
|
18 |
if ( !is_array( $box_args ) )
|
@@ -34,7 +34,7 @@ class P2P_Box_Factory extends P2P_Factory {
|
|
34 |
'can_create_post' => true
|
35 |
) );
|
36 |
|
37 |
-
$this->register( $
|
38 |
|
39 |
return $args;
|
40 |
}
|
@@ -71,7 +71,8 @@ class P2P_Box_Factory extends P2P_Factory {
|
|
71 |
private function create_box( $directed ) {
|
72 |
$box_args = $this->queue[ $directed->name ];
|
73 |
|
74 |
-
$title_class =
|
|
|
75 |
|
76 |
$columns = array(
|
77 |
'delete' => new P2P_Field_Delete,
|
5 |
class P2P_Box_Factory extends P2P_Factory {
|
6 |
|
7 |
function __construct() {
|
8 |
+
add_action( 'p2p_registered_connection_type', array( $this, 'filter_ctypes' ), 10, 2 );
|
9 |
|
10 |
add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
|
11 |
add_action( 'save_post', array( $this, 'save_post' ), 10, 2 );
|
12 |
add_action( 'wp_ajax_p2p_box', array( $this, 'wp_ajax_p2p_box' ) );
|
13 |
}
|
14 |
|
15 |
+
function filter_ctypes( $ctype, $args ) {
|
16 |
if ( isset( $args['admin_box'] ) ) {
|
17 |
$box_args = _p2p_pluck( $args, 'admin_box' );
|
18 |
if ( !is_array( $box_args ) )
|
34 |
'can_create_post' => true
|
35 |
) );
|
36 |
|
37 |
+
$this->register( $ctype->name, $box_args );
|
38 |
|
39 |
return $args;
|
40 |
}
|
71 |
private function create_box( $directed ) {
|
72 |
$box_args = $this->queue[ $directed->name ];
|
73 |
|
74 |
+
$title_class = str_replace( 'P2P_Side_', 'P2P_Field_Title_',
|
75 |
+
get_class( $directed->get( 'opposite', 'side' ) ) );
|
76 |
|
77 |
$columns = array(
|
78 |
'delete' => new P2P_Field_Delete,
|
admin/box.css
CHANGED
@@ -117,11 +117,11 @@ td.p2p-col-create .p2p-icon {
|
|
117 |
}
|
118 |
|
119 |
.p2p-col-delete .p2p-icon {
|
120 |
-
background: url("images/
|
121 |
}
|
122 |
|
123 |
.p2p-col-create .p2p-icon {
|
124 |
-
background: url("images/
|
125 |
float: left;
|
126 |
margin-right: 6px;
|
127 |
}
|
117 |
}
|
118 |
|
119 |
.p2p-col-delete .p2p-icon {
|
120 |
+
background: url("images/minus.png") no-repeat scroll 50% 50% transparent;
|
121 |
}
|
122 |
|
123 |
.p2p-col-create .p2p-icon {
|
124 |
+
background: url("images/plus.png") no-repeat scroll 50% 50% transparent;
|
125 |
float: left;
|
126 |
margin-right: 6px;
|
127 |
}
|
admin/box.php
CHANGED
@@ -12,6 +12,8 @@ class P2P_Box {
|
|
12 |
|
13 |
private $columns;
|
14 |
|
|
|
|
|
15 |
private static $admin_box_qv = array(
|
16 |
'update_post_term_cache' => false,
|
17 |
'update_post_meta_cache' => false,
|
@@ -29,6 +31,10 @@ class P2P_Box {
|
|
29 |
}
|
30 |
|
31 |
public function init_scripts() {
|
|
|
|
|
|
|
|
|
32 |
wp_enqueue_style( 'p2p-box', plugins_url( 'box.css', __FILE__ ), array(), P2P_PLUGIN_VERSION );
|
33 |
|
34 |
wp_enqueue_script( 'p2p-box', plugins_url( 'box.js', __FILE__ ), array( 'jquery' ), P2P_PLUGIN_VERSION, true );
|
@@ -37,6 +43,9 @@ class P2P_Box {
|
|
37 |
'spinner' => admin_url( 'images/wpspin_light.gif' ),
|
38 |
'deleteConfirmMessage' => __( 'Are you sure you want to delete all connections?', P2P_TEXTDOMAIN ),
|
39 |
) );
|
|
|
|
|
|
|
40 |
}
|
41 |
|
42 |
function render( $post ) {
|
12 |
|
13 |
private $columns;
|
14 |
|
15 |
+
private static $enqueued_scripts = false;
|
16 |
+
|
17 |
private static $admin_box_qv = array(
|
18 |
'update_post_term_cache' => false,
|
19 |
'update_post_meta_cache' => false,
|
31 |
}
|
32 |
|
33 |
public function init_scripts() {
|
34 |
+
|
35 |
+
if ( self::$enqueued_scripts )
|
36 |
+
return;
|
37 |
+
|
38 |
wp_enqueue_style( 'p2p-box', plugins_url( 'box.css', __FILE__ ), array(), P2P_PLUGIN_VERSION );
|
39 |
|
40 |
wp_enqueue_script( 'p2p-box', plugins_url( 'box.js', __FILE__ ), array( 'jquery' ), P2P_PLUGIN_VERSION, true );
|
43 |
'spinner' => admin_url( 'images/wpspin_light.gif' ),
|
44 |
'deleteConfirmMessage' => __( 'Are you sure you want to delete all connections?', P2P_TEXTDOMAIN ),
|
45 |
) );
|
46 |
+
|
47 |
+
self::$enqueued_scripts = true;
|
48 |
+
|
49 |
}
|
50 |
|
51 |
function render( $post ) {
|
admin/column-factory.php
CHANGED
@@ -3,12 +3,12 @@
|
|
3 |
class P2P_Column_Factory extends P2P_Factory {
|
4 |
|
5 |
function __construct() {
|
6 |
-
|
7 |
|
8 |
add_action( 'admin_print_styles', array( $this, 'add_columns' ) );
|
9 |
}
|
10 |
|
11 |
-
function filter_ctypes( $args ) {
|
12 |
if ( isset( $args['admin_column'] ) ) {
|
13 |
$column_args = _p2p_pluck( $args, 'admin_column' );
|
14 |
if ( !is_array( $column_args ) )
|
@@ -21,7 +21,7 @@ class P2P_Column_Factory extends P2P_Factory {
|
|
21 |
'show' => false,
|
22 |
) );
|
23 |
|
24 |
-
$this->register( $
|
25 |
|
26 |
return $args;
|
27 |
}
|
3 |
class P2P_Column_Factory extends P2P_Factory {
|
4 |
|
5 |
function __construct() {
|
6 |
+
add_action( 'p2p_registered_connection_type', array( $this, 'filter_ctypes' ), 10, 2 );
|
7 |
|
8 |
add_action( 'admin_print_styles', array( $this, 'add_columns' ) );
|
9 |
}
|
10 |
|
11 |
+
function filter_ctypes( $ctype, $args ) {
|
12 |
if ( isset( $args['admin_column'] ) ) {
|
13 |
$column_args = _p2p_pluck( $args, 'admin_column' );
|
14 |
if ( !is_array( $column_args ) )
|
21 |
'show' => false,
|
22 |
) );
|
23 |
|
24 |
+
$this->register( $ctype->name, $column_args );
|
25 |
|
26 |
return $args;
|
27 |
}
|
admin/column.php
CHANGED
@@ -8,6 +8,10 @@ abstract class P2P_Column {
|
|
8 |
|
9 |
function __construct( $directed, $items ) {
|
10 |
$this->ctype = $directed;
|
|
|
|
|
|
|
|
|
11 |
|
12 |
$extra_qv = array(
|
13 |
'p2p:per_page' => -1,
|
@@ -24,10 +28,6 @@ abstract class P2P_Column {
|
|
24 |
}
|
25 |
|
26 |
function add_column( $columns ) {
|
27 |
-
$this->column_id = sprintf( 'p2p-%s-%s',
|
28 |
-
$this->ctype->get_direction(),
|
29 |
-
$this->ctype->name
|
30 |
-
);
|
31 |
|
32 |
$columns[ $this->column_id ] = $this->ctype->get( 'current', 'title' );
|
33 |
|
@@ -37,7 +37,7 @@ abstract class P2P_Column {
|
|
37 |
function styles() {
|
38 |
?>
|
39 |
<style type="text/css">
|
40 |
-
.column-<?php echo $this->
|
41 |
margin-top: 0;
|
42 |
margin-bottom: 0;
|
43 |
}
|
8 |
|
9 |
function __construct( $directed, $items ) {
|
10 |
$this->ctype = $directed;
|
11 |
+
$this->column_id = sprintf( 'p2p-%s-%s',
|
12 |
+
$this->ctype->get_direction(),
|
13 |
+
$this->ctype->name
|
14 |
+
);
|
15 |
|
16 |
$extra_qv = array(
|
17 |
'p2p:per_page' => -1,
|
28 |
}
|
29 |
|
30 |
function add_column( $columns ) {
|
|
|
|
|
|
|
|
|
31 |
|
32 |
$columns[ $this->column_id ] = $this->ctype->get( 'current', 'title' );
|
33 |
|
37 |
function styles() {
|
38 |
?>
|
39 |
<style type="text/css">
|
40 |
+
.column-<?php echo $this->column_id; ?> ul {
|
41 |
margin-top: 0;
|
42 |
margin-bottom: 0;
|
43 |
}
|
admin/factory.php
CHANGED
@@ -24,12 +24,7 @@ abstract class P2P_Factory {
|
|
24 |
|
25 |
$directions = self::determine_directions( $ctype, $object_type, $post_type, $args->show );
|
26 |
|
27 |
-
$title = $ctype
|
28 |
-
|
29 |
-
if ( count( $directions ) > 1 && $title['from'] == $title['to'] ) {
|
30 |
-
$title['from'] .= __( ' (from)', P2P_TEXTDOMAIN );
|
31 |
-
$title['to'] .= __( ' (to)', P2P_TEXTDOMAIN );
|
32 |
-
}
|
33 |
|
34 |
foreach ( $directions as $direction ) {
|
35 |
$key = ( 'to' == $direction ) ? 'to' : 'from';
|
@@ -41,28 +36,26 @@ abstract class P2P_Factory {
|
|
41 |
}
|
42 |
}
|
43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
protected static function determine_directions( $ctype, $object_type, $post_type, $show_ui ) {
|
45 |
$direction = $ctype->direction_from_types( $object_type, $post_type );
|
46 |
if ( !$direction )
|
47 |
return array();
|
48 |
|
49 |
-
|
50 |
-
if ( $show_ui )
|
51 |
-
$directions = array( 'any' );
|
52 |
-
else
|
53 |
-
$directions = array();
|
54 |
-
} else {
|
55 |
-
if ( $ctype->indeterminate ) {
|
56 |
-
$direction = 'any';
|
57 |
-
}
|
58 |
-
|
59 |
-
$directions = array_intersect(
|
60 |
-
_p2p_expand_direction( $show_ui ),
|
61 |
-
_p2p_expand_direction( $direction )
|
62 |
-
);
|
63 |
-
}
|
64 |
-
|
65 |
-
return $directions;
|
66 |
}
|
67 |
|
68 |
abstract function add_item( $directed, $object_type, $post_type, $title );
|
24 |
|
25 |
$directions = self::determine_directions( $ctype, $object_type, $post_type, $args->show );
|
26 |
|
27 |
+
$title = self::get_title( $directions, $ctype );
|
|
|
|
|
|
|
|
|
|
|
28 |
|
29 |
foreach ( $directions as $direction ) {
|
30 |
$key = ( 'to' == $direction ) ? 'to' : 'from';
|
36 |
}
|
37 |
}
|
38 |
|
39 |
+
protected static function get_title( $directions, $ctype ) {
|
40 |
+
$title = array(
|
41 |
+
'from' => $ctype->get_field( 'title', 'from' ),
|
42 |
+
'to' => $ctype->get_field( 'title', 'to' )
|
43 |
+
);
|
44 |
+
|
45 |
+
if ( count( $directions ) > 1 && $title['from'] == $title['to'] ) {
|
46 |
+
$title['from'] .= __( ' (from)', P2P_TEXTDOMAIN );
|
47 |
+
$title['to'] .= __( ' (to)', P2P_TEXTDOMAIN );
|
48 |
+
}
|
49 |
+
|
50 |
+
return $title;
|
51 |
+
}
|
52 |
+
|
53 |
protected static function determine_directions( $ctype, $object_type, $post_type, $show_ui ) {
|
54 |
$direction = $ctype->direction_from_types( $object_type, $post_type );
|
55 |
if ( !$direction )
|
56 |
return array();
|
57 |
|
58 |
+
return $ctype->_directions_for_admin( $direction, $show_ui );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
}
|
60 |
|
61 |
abstract function add_item( $directed, $object_type, $post_type, $title );
|
admin/images/delete.png
DELETED
Binary file
|
admin/images/minus.png
ADDED
Binary file
|
admin/images/{add.png → plus.png}
RENAMED
File without changes
|
admin/templates/connection-types-form.html
CHANGED
@@ -5,4 +5,4 @@
|
|
5 |
<option>{{.}}</option>
|
6 |
{{/options}}
|
7 |
</select>
|
8 |
-
<input class="button" type="submit" name="p2p_convert" value="{{{button_text}}}" />
|
5 |
<option>{{.}}</option>
|
6 |
{{/options}}
|
7 |
</select>
|
8 |
+
<input class="button button-small" type="submit" name="p2p_convert" value="{{{button_text}}}" />
|
command.php
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
WP_CLI::add_command( 'p2p', 'P2P_CLI_Command' );
|
4 |
+
|
5 |
+
class P2P_CLI_Command extends WP_CLI_Command {
|
6 |
+
|
7 |
+
/**
|
8 |
+
* List registered connection types.
|
9 |
+
*
|
10 |
+
* @subcommand connection-types
|
11 |
+
*/
|
12 |
+
function connection_types() {
|
13 |
+
foreach ( P2P_Connection_Type_Factory::get_all_instances() as $p2p_type => $ctype ) {
|
14 |
+
WP_CLI::line( $p2p_type );
|
15 |
+
}
|
16 |
+
}
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Generate connections for a specific connection type.
|
20 |
+
*
|
21 |
+
* @subcommand generate-connections
|
22 |
+
* @synopsis <connection-type> [--items]
|
23 |
+
*/
|
24 |
+
function generate_connections( $args, $assoc_args ) {
|
25 |
+
list( $connection_type ) = $args;
|
26 |
+
|
27 |
+
$ctype = p2p_type( $connection_type );
|
28 |
+
if ( !$ctype )
|
29 |
+
WP_CLI::error( "'$connection_type' is not a registered connection type." );
|
30 |
+
|
31 |
+
if ( isset( $assoc_args['items'] ) ) {
|
32 |
+
foreach ( _p2p_extract_post_types( $ctype->side ) as $ptype ) {
|
33 |
+
$command = array( 'wp', 'post', 'generate' );
|
34 |
+
$assoc_args = array( 'post_type' => $ptype );
|
35 |
+
|
36 |
+
WP_CLI::launch( WP_CLI::compose_args( $command, $assoc_args ) );
|
37 |
+
}
|
38 |
+
}
|
39 |
+
|
40 |
+
$count = $this->_generate_c( $ctype );
|
41 |
+
|
42 |
+
WP_CLI::success( "Created $count connections." );
|
43 |
+
}
|
44 |
+
|
45 |
+
private function _generate_c( $ctype ) {
|
46 |
+
$extra_qv = array( 'p2p:per_page' => 10 );
|
47 |
+
|
48 |
+
$candidate = $ctype
|
49 |
+
->set_direction( 'from' )
|
50 |
+
->get_connectable( 'any', $extra_qv, 'abstract' );
|
51 |
+
|
52 |
+
$count = 0;
|
53 |
+
|
54 |
+
foreach ( $candidate->items as $from ) {
|
55 |
+
$eligible = $ctype->get_connectable( $from, array(
|
56 |
+
'p2p:per_page' => rand( 0, 5 )
|
57 |
+
), 'abstract' );
|
58 |
+
|
59 |
+
foreach ( $eligible->items as $to ) {
|
60 |
+
$r = $ctype->connect( $from, $to );
|
61 |
+
|
62 |
+
if ( is_wp_error( $r ) )
|
63 |
+
WP_CLI::warning( $r );
|
64 |
+
else
|
65 |
+
$count++;
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
return $count;
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Set up the example connections.
|
74 |
+
*
|
75 |
+
* @subcommand setup-example
|
76 |
+
*/
|
77 |
+
function setup_example() {
|
78 |
+
$ctype = p2p_type( 'actor_movie' );
|
79 |
+
|
80 |
+
$data = array(
|
81 |
+
'Nicholas Cage' => array( 'Lord Of War', 'Adaptation' ),
|
82 |
+
'Jude Law' => array( 'Sherlock Holmes' ),
|
83 |
+
'Brad Pitt' => array( '7 Years In Tibet', 'Fight Club' ),
|
84 |
+
'Natalie Portman' => array( 'Black Swan', 'Thor' ),
|
85 |
+
'Matt Damon' => array( 'The Talented Mr. Ripley' ),
|
86 |
+
'Charlize Theron' => array(),
|
87 |
+
);
|
88 |
+
|
89 |
+
foreach ( $data as $actor_name => $movies ) {
|
90 |
+
$actor = self::titled_post( 'actor', $actor_name );
|
91 |
+
|
92 |
+
foreach ( $movies as $movie_title ) {
|
93 |
+
$movie = self::titled_post( 'movie', $movie_title );
|
94 |
+
|
95 |
+
$ctype->connect( $actor, $movie );
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
WP_CLI::success( "Set up the actors and movies example." );
|
100 |
+
}
|
101 |
+
|
102 |
+
private static function titled_post( $type, $title ) {
|
103 |
+
return wp_insert_post( array(
|
104 |
+
'post_type' => $type,
|
105 |
+
'post_title' => $title,
|
106 |
+
'post_status' => 'publish'
|
107 |
+
) );
|
108 |
+
}
|
109 |
+
}
|
110 |
+
|
core/api.php
CHANGED
@@ -77,7 +77,11 @@ function p2p_register_connection_type( $args ) {
|
|
77 |
$args['admin_box']['context'] = _p2p_pluck( $args, 'context' );
|
78 |
}
|
79 |
|
80 |
-
|
|
|
|
|
|
|
|
|
81 |
}
|
82 |
|
83 |
/**
|
@@ -321,6 +325,9 @@ function p2p_list_posts( $posts, $args = array() ) {
|
|
321 |
if ( is_a( $posts, 'P2P_List' ) ) {
|
322 |
$list = $posts;
|
323 |
} else {
|
|
|
|
|
|
|
324 |
$list = new P2P_List( $posts, 'P2P_Item_Post' );
|
325 |
}
|
326 |
|
77 |
$args['admin_box']['context'] = _p2p_pluck( $args, 'context' );
|
78 |
}
|
79 |
|
80 |
+
$ctype = P2P_Connection_Type_Factory::register( $args );
|
81 |
+
|
82 |
+
do_action( 'p2p_registered_connection_type', $ctype, $args );
|
83 |
+
|
84 |
+
return $ctype;
|
85 |
}
|
86 |
|
87 |
/**
|
325 |
if ( is_a( $posts, 'P2P_List' ) ) {
|
326 |
$list = $posts;
|
327 |
} else {
|
328 |
+
if ( is_a( $posts, 'WP_Query' ) )
|
329 |
+
$posts = $posts->posts;
|
330 |
+
|
331 |
$list = new P2P_List( $posts, 'P2P_Item_Post' );
|
332 |
}
|
333 |
|
core/directed-type.php
CHANGED
@@ -34,27 +34,21 @@ class P2P_Directed_Connection_Type {
|
|
34 |
return $this->set_direction( _p2p_flip_direction( $this->direction ) );
|
35 |
}
|
36 |
|
37 |
-
public function get( $side, $
|
38 |
-
|
39 |
-
|
40 |
-
$map = array(
|
41 |
'to' => 'to',
|
42 |
'from' => 'from',
|
43 |
'any' => 'from'
|
44 |
-
)
|
45 |
-
|
46 |
-
case 'opposite':
|
47 |
-
$map = array(
|
48 |
'to' => 'from',
|
49 |
'from' => 'to',
|
50 |
'any' => 'to'
|
51 |
-
)
|
52 |
-
|
53 |
-
}
|
54 |
-
|
55 |
-
$arg = $this->ctype->$key;
|
56 |
|
57 |
-
return $
|
58 |
}
|
59 |
|
60 |
private function abstract_query( $qv, $which, $output = 'abstract' ) {
|
@@ -69,6 +63,16 @@ class P2P_Directed_Connection_Type {
|
|
69 |
return $side->get_list( $query );
|
70 |
}
|
71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
protected function recognize( $item, $which = 'current' ) {
|
73 |
return $this->get( $which, 'side' )->item_recognize( $item );
|
74 |
}
|
@@ -137,7 +141,7 @@ class P2P_Directed_Connection_Type {
|
|
137 |
public function get_connectable( $arg, $extra_qv = array(), $output = 'raw' ) {
|
138 |
$side = $this->get( 'opposite', 'side' );
|
139 |
|
140 |
-
$item = $this->
|
141 |
|
142 |
$extra_qv['p2p:exclude'] = $this->get_non_connectable( $item, $extra_qv );
|
143 |
|
@@ -158,6 +162,8 @@ class P2P_Directed_Connection_Type {
|
|
158 |
}
|
159 |
|
160 |
$extra_qv['fields'] = 'ids';
|
|
|
|
|
161 |
$already_connected = $this->get_connected( $to_check, $extra_qv, 'abstract' )->items;
|
162 |
|
163 |
_p2p_append( $to_exclude, $already_connected );
|
@@ -165,22 +171,6 @@ class P2P_Directed_Connection_Type {
|
|
165 |
return $to_exclude;
|
166 |
}
|
167 |
|
168 |
-
private function _check_params( $from_arg, $to_arg ) {
|
169 |
-
$from = $this->recognize( $from_arg, 'current' );
|
170 |
-
if ( !$from )
|
171 |
-
return new WP_Error( 'first_parameter', 'Invalid first parameter.' );
|
172 |
-
|
173 |
-
if ( 'any' == $to_arg ) {
|
174 |
-
$to = 'any';
|
175 |
-
} else {
|
176 |
-
$to = $this->recognize( $to_arg, 'opposite' );
|
177 |
-
if ( !$to )
|
178 |
-
return new WP_Error( 'second_parameter', 'Invalid second parameter.' );
|
179 |
-
}
|
180 |
-
|
181 |
-
return compact( 'from', 'to' );
|
182 |
-
}
|
183 |
-
|
184 |
/**
|
185 |
* Connect two items.
|
186 |
*
|
@@ -190,12 +180,14 @@ class P2P_Directed_Connection_Type {
|
|
190 |
*
|
191 |
* @return int|object p2p_id or WP_Error on failure
|
192 |
*/
|
193 |
-
public function connect( $
|
194 |
-
$
|
195 |
-
if (
|
196 |
-
return
|
197 |
|
198 |
-
|
|
|
|
|
199 |
|
200 |
if ( !$this->self_connections && $from->get_id() == $to->get_id() )
|
201 |
return new WP_Error( 'self_connection', 'Connection between an element and itself is not allowed.' );
|
@@ -240,7 +232,7 @@ class P2P_Directed_Connection_Type {
|
|
240 |
|
241 |
protected function get_default( $args, $p2p_id ) {
|
242 |
if ( isset( $args['default_cb'] ) )
|
243 |
-
return call_user_func( $args['default_cb'], p2p_get_connection( $p2p_id ) );
|
244 |
|
245 |
if ( !isset( $args['default'] ) )
|
246 |
return null;
|
@@ -256,12 +248,16 @@ class P2P_Directed_Connection_Type {
|
|
256 |
*
|
257 |
* @return int|object count or WP_Error on failure
|
258 |
*/
|
259 |
-
public function disconnect( $
|
260 |
-
$
|
261 |
-
if (
|
262 |
-
return
|
|
|
|
|
|
|
|
|
263 |
|
264 |
-
return $this->delete_connections(
|
265 |
}
|
266 |
|
267 |
public function get_p2p_id( $from, $to ) {
|
@@ -275,10 +271,17 @@ class P2P_Directed_Connection_Type {
|
|
275 |
/**
|
276 |
* Transforms $this->get_connections( ... ) into p2p_get_connections( $this->name, ... ) etc.
|
277 |
*/
|
278 |
-
public function __call( $method, $
|
279 |
-
$args
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
280 |
|
281 |
-
return call_user_func( 'p2p_' . $method, $this->name, $args
|
282 |
}
|
283 |
}
|
284 |
|
34 |
return $this->set_direction( _p2p_flip_direction( $this->direction ) );
|
35 |
}
|
36 |
|
37 |
+
public function get( $side, $field ) {
|
38 |
+
static $map = array(
|
39 |
+
'current' => array(
|
|
|
40 |
'to' => 'to',
|
41 |
'from' => 'from',
|
42 |
'any' => 'from'
|
43 |
+
),
|
44 |
+
'opposite' => array(
|
|
|
|
|
45 |
'to' => 'from',
|
46 |
'from' => 'to',
|
47 |
'any' => 'to'
|
48 |
+
)
|
49 |
+
);
|
|
|
|
|
|
|
50 |
|
51 |
+
return $this->ctype->get_field( $field, $map[ $side ][ $this->direction ] );
|
52 |
}
|
53 |
|
54 |
private function abstract_query( $qv, $which, $output = 'abstract' ) {
|
63 |
return $side->get_list( $query );
|
64 |
}
|
65 |
|
66 |
+
protected function recognize_any( $item, $which = 'current' ) {
|
67 |
+
if ( 'any' == $item )
|
68 |
+
return new P2P_Item_Any;
|
69 |
+
|
70 |
+
if ( is_a( $item, 'P2P_Item_Any' ) )
|
71 |
+
return $item;
|
72 |
+
|
73 |
+
return $this->recognize( $item, $which );
|
74 |
+
}
|
75 |
+
|
76 |
protected function recognize( $item, $which = 'current' ) {
|
77 |
return $this->get( $which, 'side' )->item_recognize( $item );
|
78 |
}
|
141 |
public function get_connectable( $arg, $extra_qv = array(), $output = 'raw' ) {
|
142 |
$side = $this->get( 'opposite', 'side' );
|
143 |
|
144 |
+
$item = $this->recognize_any( $arg );
|
145 |
|
146 |
$extra_qv['p2p:exclude'] = $this->get_non_connectable( $item, $extra_qv );
|
147 |
|
162 |
}
|
163 |
|
164 |
$extra_qv['fields'] = 'ids';
|
165 |
+
$extra_qv['p2p:per_page'] = -1;
|
166 |
+
|
167 |
$already_connected = $this->get_connected( $to_check, $extra_qv, 'abstract' )->items;
|
168 |
|
169 |
_p2p_append( $to_exclude, $already_connected );
|
171 |
return $to_exclude;
|
172 |
}
|
173 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
/**
|
175 |
* Connect two items.
|
176 |
*
|
180 |
*
|
181 |
* @return int|object p2p_id or WP_Error on failure
|
182 |
*/
|
183 |
+
public function connect( $from_arg, $to_arg, $meta = array() ) {
|
184 |
+
$from = $this->recognize( $from_arg, 'current' );
|
185 |
+
if ( !$from )
|
186 |
+
return new WP_Error( 'first_parameter', 'Invalid first parameter.' );
|
187 |
|
188 |
+
$to = $this->recognize( $to_arg, 'opposite' );
|
189 |
+
if ( !$to )
|
190 |
+
return new WP_Error( 'second_parameter', 'Invalid second parameter.' );
|
191 |
|
192 |
if ( !$this->self_connections && $from->get_id() == $to->get_id() )
|
193 |
return new WP_Error( 'self_connection', 'Connection between an element and itself is not allowed.' );
|
232 |
|
233 |
protected function get_default( $args, $p2p_id ) {
|
234 |
if ( isset( $args['default_cb'] ) )
|
235 |
+
return call_user_func( $args['default_cb'], p2p_get_connection( $p2p_id ), $this->direction );
|
236 |
|
237 |
if ( !isset( $args['default'] ) )
|
238 |
return null;
|
248 |
*
|
249 |
* @return int|object count or WP_Error on failure
|
250 |
*/
|
251 |
+
public function disconnect( $from_arg, $to_arg ) {
|
252 |
+
$from = $this->recognize( $from_arg, 'current' );
|
253 |
+
if ( !$from )
|
254 |
+
return new WP_Error( 'first_parameter', 'Invalid first parameter.' );
|
255 |
+
|
256 |
+
$to = $this->recognize_any( $to_arg, 'opposite' );
|
257 |
+
if ( !$to )
|
258 |
+
return new WP_Error( 'second_parameter', 'Invalid second parameter.' );
|
259 |
|
260 |
+
return $this->delete_connections( compact( 'from', 'to' ) );
|
261 |
}
|
262 |
|
263 |
public function get_p2p_id( $from, $to ) {
|
271 |
/**
|
272 |
* Transforms $this->get_connections( ... ) into p2p_get_connections( $this->name, ... ) etc.
|
273 |
*/
|
274 |
+
public function __call( $method, $argv ) {
|
275 |
+
list( $args ) = $argv;
|
276 |
+
|
277 |
+
$args['direction'] = $this->direction;
|
278 |
+
|
279 |
+
foreach ( array( 'from', 'to' ) as $key ) {
|
280 |
+
if ( isset( $args[ $key ] ) && is_a( $args[ $key ], 'P2P_Item_Any' ) )
|
281 |
+
$args[ $key ] = 'any';
|
282 |
+
}
|
283 |
|
284 |
+
return call_user_func( 'p2p_' . $method, $this->name, $args );
|
285 |
}
|
286 |
}
|
287 |
|
core/extra.php
CHANGED
@@ -141,18 +141,31 @@ function _p2p_get_list( $args ) {
|
|
141 |
|
142 |
$connected = $directed->$method( $item, $extra_qv, 'abstract' );
|
143 |
|
144 |
-
$
|
145 |
-
|
146 |
-
|
147 |
-
|
|
|
|
|
148 |
|
149 |
-
|
150 |
-
|
151 |
'before_list' => '<ol id="' . $ctype->name . '_list">',
|
152 |
'after_list' => '</ol>',
|
153 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
}
|
155 |
|
|
|
|
|
156 |
return apply_filters( "p2p_{$context}_html", $connected->render( $args ), $connected, $directed, $mode );
|
157 |
}
|
158 |
|
141 |
|
142 |
$connected = $directed->$method( $item, $extra_qv, 'abstract' );
|
143 |
|
144 |
+
switch ( $mode ) {
|
145 |
+
case 'inline':
|
146 |
+
$args = array(
|
147 |
+
'separator' => ', '
|
148 |
+
);
|
149 |
+
break;
|
150 |
|
151 |
+
case 'ol':
|
152 |
+
$args = array(
|
153 |
'before_list' => '<ol id="' . $ctype->name . '_list">',
|
154 |
'after_list' => '</ol>',
|
155 |
+
);
|
156 |
+
break;
|
157 |
+
|
158 |
+
case 'ul':
|
159 |
+
default:
|
160 |
+
$args = array(
|
161 |
+
'before_list' => '<ul id="' . $ctype->name . '_list">',
|
162 |
+
'after_list' => '</ul>',
|
163 |
+
);
|
164 |
+
break;
|
165 |
}
|
166 |
|
167 |
+
$args['echo'] = false;
|
168 |
+
|
169 |
return apply_filters( "p2p_{$context}_html", $connected->render( $args ), $connected, $directed, $mode );
|
170 |
}
|
171 |
|
core/indeterminate-type.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
class
|
4 |
|
5 |
protected function recognize( $arg ) {
|
6 |
foreach ( array( 'current', 'opposite' ) as $side ) {
|
@@ -23,8 +23,12 @@ class P2P_Indeterminate_Connection_Type extends P2P_Directed_Connection_Type {
|
|
23 |
$other_qv = $this->get( 'opposite', 'side' )->get_base_qv( $q );
|
24 |
|
25 |
// need to be inclusive
|
26 |
-
if ( isset( $other_qv['post_type'] ) )
|
27 |
-
|
|
|
|
|
|
|
|
|
28 |
|
29 |
return $args;
|
30 |
}
|
1 |
<?php
|
2 |
|
3 |
+
class P2P_Indeterminate_Directed_Connection_Type extends P2P_Directed_Connection_Type {
|
4 |
|
5 |
protected function recognize( $arg ) {
|
6 |
foreach ( array( 'current', 'opposite' ) as $side ) {
|
23 |
$other_qv = $this->get( 'opposite', 'side' )->get_base_qv( $q );
|
24 |
|
25 |
// need to be inclusive
|
26 |
+
if ( isset( $other_qv['post_type'] ) ) {
|
27 |
+
$args['post_type'] = array_unique( array_merge(
|
28 |
+
(array) $args['post_type'],
|
29 |
+
(array) $other_qv['post_type']
|
30 |
+
) );
|
31 |
+
}
|
32 |
|
33 |
return $args;
|
34 |
}
|
core/item.php
CHANGED
@@ -33,6 +33,24 @@ abstract class P2P_Item {
|
|
33 |
}
|
34 |
|
35 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
class P2P_Item_Post extends P2P_Item {
|
37 |
|
38 |
function get_title() {
|
33 |
}
|
34 |
|
35 |
|
36 |
+
class P2P_Item_Any extends P2P_Item {
|
37 |
+
|
38 |
+
function __construct() {}
|
39 |
+
|
40 |
+
function get_permalink() {}
|
41 |
+
|
42 |
+
function get_title() {}
|
43 |
+
|
44 |
+
function get_object() {
|
45 |
+
return 'any';
|
46 |
+
}
|
47 |
+
|
48 |
+
function get_id() {
|
49 |
+
return false;
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
|
54 |
class P2P_Item_Post extends P2P_Item {
|
55 |
|
56 |
function get_title() {
|
core/list.php
CHANGED
@@ -44,7 +44,7 @@ class P2P_List {
|
|
44 |
if ( $separator ) {
|
45 |
$list = array();
|
46 |
foreach ( $this->items as $item ) {
|
47 |
-
$list[] = $this->render_item( $item
|
48 |
}
|
49 |
echo implode( $separator, $list );
|
50 |
} else {
|
44 |
if ( $separator ) {
|
45 |
$list = array();
|
46 |
foreach ( $this->items as $item ) {
|
47 |
+
$list[] = $this->render_item( $item );
|
48 |
}
|
49 |
echo implode( $separator, $list );
|
50 |
} else {
|
core/query.php
CHANGED
@@ -199,7 +199,7 @@ class P2P_Query {
|
|
199 |
if ( $this->order_num )
|
200 |
$field .= '+0';
|
201 |
|
202 |
-
$clauses['orderby'] = "p2pm_order.$field $order";
|
203 |
}
|
204 |
|
205 |
return $clauses;
|
199 |
if ( $this->order_num )
|
200 |
$field .= '+0';
|
201 |
|
202 |
+
$clauses['orderby'] = "p2pm_order.$field $order, " . str_replace( 'ORDER BY ', '', $clauses['orderby'] );
|
203 |
}
|
204 |
|
205 |
return $clauses;
|
core/side.php
CHANGED
@@ -2,6 +2,10 @@
|
|
2 |
|
3 |
abstract class P2P_Side {
|
4 |
|
|
|
|
|
|
|
|
|
5 |
abstract function get_title();
|
6 |
abstract function get_desc();
|
7 |
abstract function get_labels();
|
@@ -12,21 +16,28 @@ abstract class P2P_Side {
|
|
12 |
abstract function get_base_qv( $q );
|
13 |
abstract function translate_qv( $qv );
|
14 |
abstract function do_query( $args );
|
15 |
-
abstract function get_list( $query );
|
16 |
abstract function capture_query( $args );
|
|
|
17 |
|
18 |
abstract function is_indeterminate( $side );
|
19 |
|
20 |
-
|
|
|
|
|
21 |
|
|
|
|
|
|
|
22 |
function item_recognize( $arg ) {
|
23 |
$class = $this->item_type;
|
24 |
|
25 |
-
if ( is_a( $arg,
|
26 |
-
|
|
|
|
|
27 |
|
28 |
-
|
29 |
-
|
30 |
|
31 |
$raw_item = $this->recognize( $arg );
|
32 |
if ( !$raw_item )
|
@@ -34,6 +45,11 @@ abstract class P2P_Side {
|
|
34 |
|
35 |
return new $class( $raw_item );
|
36 |
}
|
|
|
|
|
|
|
|
|
|
|
37 |
}
|
38 |
|
39 |
|
@@ -45,6 +61,10 @@ class P2P_Side_Post extends P2P_Side {
|
|
45 |
$this->query_vars = $query_vars;
|
46 |
}
|
47 |
|
|
|
|
|
|
|
|
|
48 |
public function first_post_type() {
|
49 |
return $this->query_vars['post_type'][0];
|
50 |
}
|
@@ -81,7 +101,7 @@ class P2P_Side_Post extends P2P_Side {
|
|
81 |
}
|
82 |
|
83 |
function get_labels() {
|
84 |
-
return
|
85 |
}
|
86 |
|
87 |
function can_edit_connections() {
|
@@ -98,17 +118,24 @@ class P2P_Side_Post extends P2P_Side {
|
|
98 |
return true;
|
99 |
}
|
100 |
|
101 |
-
function
|
102 |
-
|
103 |
-
|
|
|
|
|
|
|
|
|
|
|
104 |
|
105 |
-
|
106 |
-
|
|
|
107 |
|
108 |
-
|
109 |
-
|
110 |
|
111 |
-
|
|
|
112 |
}
|
113 |
|
114 |
function capture_query( $args ) {
|
@@ -120,20 +147,13 @@ class P2P_Side_Post extends P2P_Side {
|
|
120 |
return $q->_p2p_sql;
|
121 |
}
|
122 |
|
123 |
-
function
|
124 |
-
$
|
125 |
-
'include' => 'post__in',
|
126 |
-
'exclude' => 'post__not_in',
|
127 |
-
'search' => 's',
|
128 |
-
'page' => 'paged',
|
129 |
-
'per_page' => 'posts_per_page'
|
130 |
-
);
|
131 |
|
132 |
-
|
133 |
-
|
134 |
-
$qv[$new] = _p2p_pluck( $qv, "p2p:$old" );
|
135 |
|
136 |
-
return $
|
137 |
}
|
138 |
|
139 |
function is_indeterminate( $side ) {
|
@@ -145,27 +165,10 @@ class P2P_Side_Post extends P2P_Side {
|
|
145 |
return !empty( $common );
|
146 |
}
|
147 |
|
148 |
-
function
|
149 |
-
$
|
150 |
-
|
151 |
-
if ( is_a( $arg, $class ) ) {
|
152 |
-
if ( !$this->recognize_post_type( $arg->post_type ) )
|
153 |
-
return false;
|
154 |
-
|
155 |
-
return $arg;
|
156 |
-
}
|
157 |
-
|
158 |
-
if ( is_a( $arg, 'P2P_Item' ) )
|
159 |
-
return false;
|
160 |
-
|
161 |
-
$raw_item = $this->recognize( $arg );
|
162 |
-
if ( !$raw_item )
|
163 |
return false;
|
164 |
|
165 |
-
return new $class( $raw_item );
|
166 |
-
}
|
167 |
-
|
168 |
-
protected function recognize( $arg ) {
|
169 |
$post = get_post( $arg );
|
170 |
|
171 |
if ( !is_object( $post ) )
|
@@ -216,6 +219,10 @@ class P2P_Side_User extends P2P_Side {
|
|
216 |
$this->query_vars = $query_vars;
|
217 |
}
|
218 |
|
|
|
|
|
|
|
|
|
219 |
function get_desc() {
|
220 |
return __( 'Users', P2P_TEXTDOMAIN );
|
221 |
}
|
@@ -225,7 +232,7 @@ class P2P_Side_User extends P2P_Side {
|
|
225 |
}
|
226 |
|
227 |
function get_labels() {
|
228 |
-
return array(
|
229 |
'singular_name' => __( 'User', P2P_TEXTDOMAIN ),
|
230 |
'search_items' => __( 'Search Users', P2P_TEXTDOMAIN ),
|
231 |
'not_found' => __( 'No users found.', P2P_TEXTDOMAIN ),
|
@@ -240,22 +247,28 @@ class P2P_Side_User extends P2P_Side {
|
|
240 |
return false;
|
241 |
}
|
242 |
|
243 |
-
function
|
244 |
-
|
245 |
-
|
246 |
|
247 |
-
|
248 |
-
|
249 |
|
250 |
-
$qv
|
|
|
251 |
|
252 |
-
if ( isset( $qv['p2p:page'] ) ) {
|
253 |
-
$
|
254 |
-
$
|
255 |
}
|
256 |
|
257 |
-
return $
|
258 |
}
|
|
|
|
|
|
|
|
|
|
|
259 |
function capture_query( $args ) {
|
260 |
$args['count_total'] = false;
|
261 |
|
@@ -287,22 +300,17 @@ class P2P_Side_User extends P2P_Side {
|
|
287 |
return "SELECT $uq->query_fields $uq->query_from $uq->query_where $uq->query_orderby $uq->query_limit";
|
288 |
}
|
289 |
|
290 |
-
function
|
291 |
-
|
292 |
-
$qv['include'] = _p2p_pluck( $qv, 'p2p:include' );
|
293 |
-
|
294 |
-
if ( isset( $qv['p2p:exclude'] ) )
|
295 |
-
$qv['exclude'] = _p2p_pluck( $qv, 'p2p:exclude' );
|
296 |
|
297 |
-
|
298 |
-
$qv['search'] = '*' . _p2p_pluck( $qv, 'p2p:search' ) . '*';
|
299 |
|
300 |
-
if ( isset( $qv['p2p:page'] )
|
301 |
-
$
|
302 |
-
$
|
303 |
}
|
304 |
|
305 |
-
return $
|
306 |
}
|
307 |
|
308 |
function is_indeterminate( $side ) {
|
2 |
|
3 |
abstract class P2P_Side {
|
4 |
|
5 |
+
protected $item_type;
|
6 |
+
|
7 |
+
abstract function get_object_type();
|
8 |
+
|
9 |
abstract function get_title();
|
10 |
abstract function get_desc();
|
11 |
abstract function get_labels();
|
16 |
abstract function get_base_qv( $q );
|
17 |
abstract function translate_qv( $qv );
|
18 |
abstract function do_query( $args );
|
|
|
19 |
abstract function capture_query( $args );
|
20 |
+
abstract function get_list( $query );
|
21 |
|
22 |
abstract function is_indeterminate( $side );
|
23 |
|
24 |
+
final function is_same_type( $side ) {
|
25 |
+
return $this->get_object_type() == $side->get_object_type();
|
26 |
+
}
|
27 |
|
28 |
+
/**
|
29 |
+
* @param object Raw object or P2P_Item
|
30 |
+
*/
|
31 |
function item_recognize( $arg ) {
|
32 |
$class = $this->item_type;
|
33 |
|
34 |
+
if ( is_a( $arg, 'P2P_Item' ) ) {
|
35 |
+
if ( !is_a( $arg, $class ) ) {
|
36 |
+
return false;
|
37 |
+
}
|
38 |
|
39 |
+
$arg = $arg->get_object();
|
40 |
+
}
|
41 |
|
42 |
$raw_item = $this->recognize( $arg );
|
43 |
if ( !$raw_item )
|
45 |
|
46 |
return new $class( $raw_item );
|
47 |
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* @param object Raw object
|
51 |
+
*/
|
52 |
+
abstract protected function recognize( $arg );
|
53 |
}
|
54 |
|
55 |
|
61 |
$this->query_vars = $query_vars;
|
62 |
}
|
63 |
|
64 |
+
public function get_object_type() {
|
65 |
+
return 'post';
|
66 |
+
}
|
67 |
+
|
68 |
public function first_post_type() {
|
69 |
return $this->query_vars['post_type'][0];
|
70 |
}
|
101 |
}
|
102 |
|
103 |
function get_labels() {
|
104 |
+
return $this->get_ptype()->labels;
|
105 |
}
|
106 |
|
107 |
function can_edit_connections() {
|
118 |
return true;
|
119 |
}
|
120 |
|
121 |
+
function translate_qv( $qv ) {
|
122 |
+
$map = array(
|
123 |
+
'include' => 'post__in',
|
124 |
+
'exclude' => 'post__not_in',
|
125 |
+
'search' => 's',
|
126 |
+
'page' => 'paged',
|
127 |
+
'per_page' => 'posts_per_page'
|
128 |
+
);
|
129 |
|
130 |
+
foreach ( $map as $old => $new )
|
131 |
+
if ( isset( $qv["p2p:$old"] ) )
|
132 |
+
$qv[$new] = _p2p_pluck( $qv, "p2p:$old" );
|
133 |
|
134 |
+
return $qv;
|
135 |
+
}
|
136 |
|
137 |
+
function do_query( $args ) {
|
138 |
+
return new WP_Query( $args );
|
139 |
}
|
140 |
|
141 |
function capture_query( $args ) {
|
147 |
return $q->_p2p_sql;
|
148 |
}
|
149 |
|
150 |
+
function get_list( $wp_query ) {
|
151 |
+
$list = new P2P_List( $wp_query->posts, $this->item_type );
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
|
153 |
+
$list->current_page = max( 1, $wp_query->get('paged') );
|
154 |
+
$list->total_pages = $wp_query->max_num_pages;
|
|
|
155 |
|
156 |
+
return $list;
|
157 |
}
|
158 |
|
159 |
function is_indeterminate( $side ) {
|
165 |
return !empty( $common );
|
166 |
}
|
167 |
|
168 |
+
protected function recognize( $arg ) {
|
169 |
+
if ( is_object( $arg ) && !isset( $arg->post_type ) )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
return false;
|
171 |
|
|
|
|
|
|
|
|
|
172 |
$post = get_post( $arg );
|
173 |
|
174 |
if ( !is_object( $post ) )
|
219 |
$this->query_vars = $query_vars;
|
220 |
}
|
221 |
|
222 |
+
function get_object_type() {
|
223 |
+
return 'user';
|
224 |
+
}
|
225 |
+
|
226 |
function get_desc() {
|
227 |
return __( 'Users', P2P_TEXTDOMAIN );
|
228 |
}
|
232 |
}
|
233 |
|
234 |
function get_labels() {
|
235 |
+
return (object) array(
|
236 |
'singular_name' => __( 'User', P2P_TEXTDOMAIN ),
|
237 |
'search_items' => __( 'Search Users', P2P_TEXTDOMAIN ),
|
238 |
'not_found' => __( 'No users found.', P2P_TEXTDOMAIN ),
|
247 |
return false;
|
248 |
}
|
249 |
|
250 |
+
function translate_qv( $qv ) {
|
251 |
+
if ( isset( $qv['p2p:include'] ) )
|
252 |
+
$qv['include'] = _p2p_pluck( $qv, 'p2p:include' );
|
253 |
|
254 |
+
if ( isset( $qv['p2p:exclude'] ) )
|
255 |
+
$qv['exclude'] = _p2p_pluck( $qv, 'p2p:exclude' );
|
256 |
|
257 |
+
if ( isset( $qv['p2p:search'] ) && $qv['p2p:search'] )
|
258 |
+
$qv['search'] = '*' . _p2p_pluck( $qv, 'p2p:search' ) . '*';
|
259 |
|
260 |
+
if ( isset( $qv['p2p:page'] ) && $qv['p2p:page'] > 0 ) {
|
261 |
+
$qv['number'] = $qv['p2p:per_page'];
|
262 |
+
$qv['offset'] = $qv['p2p:per_page'] * ( $qv['p2p:page'] - 1 );
|
263 |
}
|
264 |
|
265 |
+
return $qv;
|
266 |
}
|
267 |
+
|
268 |
+
function do_query( $args ) {
|
269 |
+
return new WP_User_Query( $args );
|
270 |
+
}
|
271 |
+
|
272 |
function capture_query( $args ) {
|
273 |
$args['count_total'] = false;
|
274 |
|
300 |
return "SELECT $uq->query_fields $uq->query_from $uq->query_where $uq->query_orderby $uq->query_limit";
|
301 |
}
|
302 |
|
303 |
+
function get_list( $query ) {
|
304 |
+
$list = new P2P_List( $query->get_results(), $this->item_type );
|
|
|
|
|
|
|
|
|
305 |
|
306 |
+
$qv = $query->query_vars;
|
|
|
307 |
|
308 |
+
if ( isset( $qv['p2p:page'] ) ) {
|
309 |
+
$list->current_page = $qv['p2p:page'];
|
310 |
+
$list->total_pages = ceil( $query->get_total() / $qv['p2p:per_page'] );
|
311 |
}
|
312 |
|
313 |
+
return $list;
|
314 |
}
|
315 |
|
316 |
function is_indeterminate( $side ) {
|
core/storage.php
CHANGED
@@ -50,7 +50,7 @@ class P2P_Storage {
|
|
50 |
|
51 |
foreach ( P2P_Connection_Type_Factory::get_all_instances() as $p2p_type => $ctype ) {
|
52 |
foreach ( array( 'from', 'to' ) as $direction ) {
|
53 |
-
if ( $object_type == $ctype->
|
54 |
p2p_delete_connections( $p2p_type, array(
|
55 |
$direction => $object_id,
|
56 |
) );
|
50 |
|
51 |
foreach ( P2P_Connection_Type_Factory::get_all_instances() as $p2p_type => $ctype ) {
|
52 |
foreach ( array( 'from', 'to' ) as $direction ) {
|
53 |
+
if ( $object_type == $ctype->side[ $direction ]->get_object_type() ) {
|
54 |
p2p_delete_connections( $p2p_type, array(
|
55 |
$direction => $object_id,
|
56 |
) );
|
core/type-factory.php
CHANGED
@@ -5,16 +5,7 @@ class P2P_Connection_Type_Factory {
|
|
5 |
private static $instances = array();
|
6 |
|
7 |
public static function register( $args ) {
|
8 |
-
|
9 |
-
if ( strlen( $args['name'] ) > 44 ) {
|
10 |
-
trigger_error( sprintf( "Connection name '%s' is longer than 44 characters.", $args['name'] ), E_USER_WARNING );
|
11 |
-
return false;
|
12 |
-
}
|
13 |
-
} else {
|
14 |
-
trigger_error( "Connection types without a 'name' parameter are deprecated.", E_USER_WARNING );
|
15 |
-
}
|
16 |
-
|
17 |
-
$args = wp_parse_args( $args, array(
|
18 |
'name' => false,
|
19 |
'from_object' => 'post',
|
20 |
'to_object' => 'post',
|
@@ -32,44 +23,81 @@ class P2P_Connection_Type_Factory {
|
|
32 |
'from_labels' => '',
|
33 |
'to_labels' => '',
|
34 |
'reciprocal' => false,
|
35 |
-
)
|
36 |
|
37 |
-
$
|
38 |
|
39 |
-
|
40 |
-
|
|
|
|
|
41 |
|
42 |
-
|
43 |
-
$args[ $direction . '_object' ] = 'user';
|
44 |
-
elseif ( 'attachment' == $object )
|
45 |
-
$args[ $direction . '_object' ] = 'attachment';
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
}
|
50 |
}
|
51 |
|
52 |
if ( !$args['name'] ) {
|
53 |
-
|
54 |
-
|
55 |
-
'from_query_vars', 'to_query_vars',
|
56 |
-
'data'
|
57 |
-
) ) ) ) );
|
58 |
}
|
59 |
|
60 |
-
$args = apply_filters( 'p2p_connection_type_args', $args );
|
61 |
|
62 |
-
$
|
63 |
|
64 |
-
|
65 |
-
trigger_error( "Connection type '$ctype->name' is already defined.", E_USER_NOTICE );
|
66 |
-
}
|
67 |
|
68 |
self::$instances[ $ctype->name ] = $ctype;
|
69 |
|
70 |
return $ctype;
|
71 |
}
|
72 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
public static function get_all_instances() {
|
74 |
return self::$instances;
|
75 |
}
|
5 |
private static $instances = array();
|
6 |
|
7 |
public static function register( $args ) {
|
8 |
+
$defaults = array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
'name' => false,
|
10 |
'from_object' => 'post',
|
11 |
'to_object' => 'post',
|
23 |
'from_labels' => '',
|
24 |
'to_labels' => '',
|
25 |
'reciprocal' => false,
|
26 |
+
);
|
27 |
|
28 |
+
$args = shortcode_atts( $defaults, $args );
|
29 |
|
30 |
+
if ( strlen( $args['name'] ) > 44 ) {
|
31 |
+
trigger_error( sprintf( "Connection name '%s' is longer than 44 characters.", $args['name'] ), E_USER_WARNING );
|
32 |
+
return false;
|
33 |
+
}
|
34 |
|
35 |
+
$sides = array();
|
|
|
|
|
|
|
36 |
|
37 |
+
foreach ( array( 'from', 'to' ) as $direction ) {
|
38 |
+
$sides[ $direction ] = self::create_side( $args, $direction );
|
|
|
39 |
}
|
40 |
|
41 |
if ( !$args['name'] ) {
|
42 |
+
trigger_error( "Connection types without a 'name' parameter are deprecated.", E_USER_WARNING );
|
43 |
+
$args['name'] = self::generate_name( $sides, $args );
|
|
|
|
|
|
|
44 |
}
|
45 |
|
46 |
+
$args = apply_filters( 'p2p_connection_type_args', $args, $sides );
|
47 |
|
48 |
+
$class = self::get_ctype_class( $sides, _p2p_pluck( $args, 'reciprocal' ) );
|
49 |
|
50 |
+
$ctype = new $class( $args, $sides );
|
|
|
|
|
51 |
|
52 |
self::$instances[ $ctype->name ] = $ctype;
|
53 |
|
54 |
return $ctype;
|
55 |
}
|
56 |
|
57 |
+
private static function create_side( &$args, $direction ) {
|
58 |
+
$object = _p2p_pluck( $args, $direction );
|
59 |
+
|
60 |
+
if ( in_array( $object, array( 'user', 'attachment' ) ) )
|
61 |
+
$object_type = $object;
|
62 |
+
else
|
63 |
+
$object_type = 'post';
|
64 |
+
|
65 |
+
$query_vars = _p2p_pluck( $args, $direction . '_query_vars' );
|
66 |
+
|
67 |
+
if ( 'post' == $object_type )
|
68 |
+
$query_vars['post_type'] = (array) $object;
|
69 |
+
|
70 |
+
$class = 'P2P_Side_' . ucfirst( $object_type );
|
71 |
+
|
72 |
+
return new $class( $query_vars );
|
73 |
+
}
|
74 |
+
|
75 |
+
private static function generate_name( $sides, $args ) {
|
76 |
+
$vals = array(
|
77 |
+
$sides['from']->get_object_type(),
|
78 |
+
$sides['to']->get_object_type(),
|
79 |
+
$sides['from']->query_vars,
|
80 |
+
$sides['to']->query_vars,
|
81 |
+
$args['data']
|
82 |
+
);
|
83 |
+
|
84 |
+
return md5( serialize( $vals ) );
|
85 |
+
}
|
86 |
+
|
87 |
+
private static function get_ctype_class( $sides, $reciprocal ) {
|
88 |
+
if ( $sides['from']->is_same_type( $sides['to'] ) &&
|
89 |
+
$sides['from']->is_indeterminate( $sides['to'] ) ) {
|
90 |
+
if ( $reciprocal )
|
91 |
+
$class = 'P2P_Reciprocal_Connection_Type';
|
92 |
+
else
|
93 |
+
$class = 'P2P_Indeterminate_Connection_Type';
|
94 |
+
} else {
|
95 |
+
$class = 'P2P_Connection_Type';
|
96 |
+
}
|
97 |
+
|
98 |
+
return $class;
|
99 |
+
}
|
100 |
+
|
101 |
public static function get_all_instances() {
|
102 |
return self::$instances;
|
103 |
}
|
core/type.php
CHANGED
@@ -2,38 +2,31 @@
|
|
2 |
|
3 |
class P2P_Connection_Type {
|
4 |
|
5 |
-
|
6 |
|
7 |
-
|
8 |
|
9 |
public $side;
|
10 |
|
11 |
public $cardinality;
|
12 |
|
13 |
-
public $title;
|
14 |
-
|
15 |
public $labels;
|
16 |
|
17 |
-
|
18 |
-
foreach ( array( 'from', 'to' ) as $direction ) {
|
19 |
-
$this->object[ $direction ] = _p2p_pluck( $args, $direction . '_object' );
|
20 |
|
21 |
-
|
|
|
22 |
|
23 |
-
|
24 |
-
}
|
25 |
-
|
26 |
-
if ( $this->object['from'] == $this->object['to'] ) {
|
27 |
-
$this->indeterminate = $this->side['from']->is_indeterminate( $this->side['to'] );
|
28 |
-
} else {
|
29 |
-
$args['self_connections'] = true;
|
30 |
-
}
|
31 |
|
32 |
$this->set_cardinality( _p2p_pluck( $args, 'cardinality' ) );
|
33 |
|
34 |
-
$
|
|
|
|
|
|
|
35 |
|
36 |
-
$this->
|
37 |
|
38 |
$this->fields = $this->expand_fields( _p2p_pluck( $args, 'fields' ) );
|
39 |
|
@@ -42,6 +35,37 @@ class P2P_Connection_Type {
|
|
42 |
}
|
43 |
}
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
private function expand_fields( $fields ) {
|
46 |
foreach ( $fields as &$field_args )
|
47 |
{
|
@@ -73,38 +97,30 @@ class P2P_Connection_Type {
|
|
73 |
}
|
74 |
}
|
75 |
|
76 |
-
private function
|
77 |
-
|
78 |
-
$labels = $this->side[ $key ]->get_labels();
|
79 |
-
$labels['create'] = __( 'Create connections', P2P_TEXTDOMAIN );
|
80 |
|
81 |
-
|
82 |
|
83 |
-
|
84 |
-
|
|
|
|
|
85 |
}
|
86 |
|
87 |
-
private function expand_title( $title ) {
|
88 |
-
if ( $title && !is_array( $title ) )
|
89 |
-
return
|
90 |
-
'from' => $title,
|
91 |
-
'to' => $title,
|
92 |
-
);
|
93 |
-
}
|
94 |
|
95 |
-
|
96 |
-
|
97 |
-
continue;
|
98 |
|
99 |
-
|
100 |
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
}
|
106 |
-
|
107 |
-
return $title;
|
108 |
}
|
109 |
|
110 |
public function __call( $method, $args ) {
|
@@ -135,7 +151,7 @@ class P2P_Connection_Type {
|
|
135 |
return false;
|
136 |
|
137 |
if ( $instantiate ) {
|
138 |
-
$class = $this->
|
139 |
|
140 |
return new $class( $this, $direction );
|
141 |
}
|
@@ -173,25 +189,26 @@ class P2P_Connection_Type {
|
|
173 |
return false;
|
174 |
}
|
175 |
|
176 |
-
|
|
|
|
|
|
|
|
|
177 |
foreach ( array( 'from', 'to' ) as $direction ) {
|
178 |
$item = $this->side[ $direction ]->item_recognize( $arg );
|
179 |
|
180 |
if ( !$item )
|
181 |
continue;
|
182 |
|
183 |
-
|
184 |
-
$direction = $this->reciprocal ? 'any' : 'from';
|
185 |
-
|
186 |
-
return $direction;
|
187 |
}
|
188 |
|
189 |
return false;
|
190 |
}
|
191 |
|
192 |
-
|
193 |
-
$from = $this->
|
194 |
-
$to = $this->
|
195 |
|
196 |
if ( $from == $to && $current == $from )
|
197 |
return 'any';
|
@@ -210,17 +227,14 @@ class P2P_Connection_Type {
|
|
210 |
if ( !$this->_type_check( $direction, $object_type, $post_types ) )
|
211 |
continue;
|
212 |
|
213 |
-
|
214 |
-
$direction = $this->reciprocal ? 'any' : 'from';
|
215 |
-
|
216 |
-
return $direction;
|
217 |
}
|
218 |
|
219 |
return false;
|
220 |
}
|
221 |
|
222 |
private function _type_check( $direction, $object_type, $post_types ) {
|
223 |
-
if ( $object_type != $this->
|
224 |
return false;
|
225 |
|
226 |
$side = $this->side[ $direction ];
|
@@ -330,9 +344,11 @@ class P2P_Connection_Type {
|
|
330 |
$possible_directions = array();
|
331 |
|
332 |
foreach ( array( 'from', 'to' ) as $direction ) {
|
333 |
-
|
|
|
|
|
334 |
foreach ( $post_types as $post_type ) {
|
335 |
-
if ( $
|
336 |
$possible_directions[] = $direction;
|
337 |
}
|
338 |
}
|
@@ -368,11 +384,9 @@ class P2P_Connection_Type {
|
|
368 |
$$key = $this->side[ $key ]->get_desc();
|
369 |
}
|
370 |
|
371 |
-
$
|
372 |
-
|
373 |
-
$label = "$from $arrow $to";
|
374 |
|
375 |
-
$title = $this->title
|
376 |
|
377 |
if ( $title )
|
378 |
$label .= " ($title)";
|
@@ -381,3 +395,36 @@ class P2P_Connection_Type {
|
|
381 |
}
|
382 |
}
|
383 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
3 |
class P2P_Connection_Type {
|
4 |
|
5 |
+
protected $directed_class = 'P2P_Directed_Connection_Type';
|
6 |
|
7 |
+
protected $arrow = '→';
|
8 |
|
9 |
public $side;
|
10 |
|
11 |
public $cardinality;
|
12 |
|
|
|
|
|
13 |
public $labels;
|
14 |
|
15 |
+
protected $title;
|
|
|
|
|
16 |
|
17 |
+
public function __construct( $args, $sides ) {
|
18 |
+
$this->side = $sides;
|
19 |
|
20 |
+
$this->set_self_connections( $args );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
|
22 |
$this->set_cardinality( _p2p_pluck( $args, 'cardinality' ) );
|
23 |
|
24 |
+
$labels = array();
|
25 |
+
foreach ( array( 'from', 'to' ) as $key ) {
|
26 |
+
$labels[ $key ] = (array) _p2p_pluck( $args, $key . '_labels' );
|
27 |
+
}
|
28 |
|
29 |
+
$this->labels = $labels;
|
30 |
|
31 |
$this->fields = $this->expand_fields( _p2p_pluck( $args, 'fields' ) );
|
32 |
|
35 |
}
|
36 |
}
|
37 |
|
38 |
+
public function get_field( $field, $direction ) {
|
39 |
+
$value = $this->$field;
|
40 |
+
|
41 |
+
if ( 'title' == $field )
|
42 |
+
return $this->expand_title( $value, $direction );
|
43 |
+
|
44 |
+
if ( 'labels' == $field )
|
45 |
+
return $this->expand_labels( $value, $direction );
|
46 |
+
|
47 |
+
if ( false === $direction )
|
48 |
+
return $value;
|
49 |
+
|
50 |
+
return $value[ $direction ];
|
51 |
+
}
|
52 |
+
|
53 |
+
function _directions_for_admin( $direction, $show_ui ) {
|
54 |
+
return array_intersect(
|
55 |
+
_p2p_expand_direction( $show_ui ),
|
56 |
+
_p2p_expand_direction( $direction )
|
57 |
+
);
|
58 |
+
}
|
59 |
+
|
60 |
+
private function set_self_connections( &$args ) {
|
61 |
+
$from_side = $this->side['from'];
|
62 |
+
$to_side = $this->side['to'];
|
63 |
+
|
64 |
+
if ( !$from_side->is_same_type( $to_side ) ) {
|
65 |
+
$args['self_connections'] = true;
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
private function expand_fields( $fields ) {
|
70 |
foreach ( $fields as &$field_args )
|
71 |
{
|
97 |
}
|
98 |
}
|
99 |
|
100 |
+
private function expand_labels( $additional_labels, $key ) {
|
101 |
+
$additional_labels['create'] = __( 'Create connections', P2P_TEXTDOMAIN );
|
|
|
|
|
102 |
|
103 |
+
$labels = clone $this->side[ $key ]->get_labels();
|
104 |
|
105 |
+
foreach ( $additional_labels as $key => $var )
|
106 |
+
$labels->$key = $var;
|
107 |
+
|
108 |
+
return $labels;
|
109 |
}
|
110 |
|
111 |
+
private function expand_title( $title, $key ) {
|
112 |
+
if ( $title && !is_array( $title ) )
|
113 |
+
return $title;
|
|
|
|
|
|
|
|
|
114 |
|
115 |
+
if ( isset( $title[$key] ) )
|
116 |
+
return $title[$key];
|
|
|
117 |
|
118 |
+
$other_key = ( 'from' == $key ) ? 'to' : 'from';
|
119 |
|
120 |
+
return sprintf(
|
121 |
+
__( 'Connected %s', P2P_TEXTDOMAIN ),
|
122 |
+
$this->side[ $other_key ]->get_title()
|
123 |
+
);
|
|
|
|
|
|
|
124 |
}
|
125 |
|
126 |
public function __call( $method, $args ) {
|
151 |
return false;
|
152 |
|
153 |
if ( $instantiate ) {
|
154 |
+
$class = $this->directed_class;
|
155 |
|
156 |
return new $class( $this, $direction );
|
157 |
}
|
189 |
return false;
|
190 |
}
|
191 |
|
192 |
+
protected function choose_direction( $direction ) {
|
193 |
+
return $direction;
|
194 |
+
}
|
195 |
+
|
196 |
+
protected function direction_from_item( $arg ) {
|
197 |
foreach ( array( 'from', 'to' ) as $direction ) {
|
198 |
$item = $this->side[ $direction ]->item_recognize( $arg );
|
199 |
|
200 |
if ( !$item )
|
201 |
continue;
|
202 |
|
203 |
+
return $this->choose_direction( $direction );
|
|
|
|
|
|
|
204 |
}
|
205 |
|
206 |
return false;
|
207 |
}
|
208 |
|
209 |
+
protected function direction_from_object_type( $current ) {
|
210 |
+
$from = $this->side['from']->get_object_type();
|
211 |
+
$to = $this->side['to']->get_object_type();
|
212 |
|
213 |
if ( $from == $to && $current == $from )
|
214 |
return 'any';
|
227 |
if ( !$this->_type_check( $direction, $object_type, $post_types ) )
|
228 |
continue;
|
229 |
|
230 |
+
return $this->choose_direction( $direction );
|
|
|
|
|
|
|
231 |
}
|
232 |
|
233 |
return false;
|
234 |
}
|
235 |
|
236 |
private function _type_check( $direction, $object_type, $post_types ) {
|
237 |
+
if ( $object_type != $this->side[ $direction ]->get_object_type() )
|
238 |
return false;
|
239 |
|
240 |
$side = $this->side[ $direction ];
|
344 |
$possible_directions = array();
|
345 |
|
346 |
foreach ( array( 'from', 'to' ) as $direction ) {
|
347 |
+
$side = $this->side[ $direction ];
|
348 |
+
|
349 |
+
if ( 'post' == $side->get_object_type() ) {
|
350 |
foreach ( $post_types as $post_type ) {
|
351 |
+
if ( $side->recognize_post_type( $post_type ) ) {
|
352 |
$possible_directions[] = $direction;
|
353 |
}
|
354 |
}
|
384 |
$$key = $this->side[ $key ]->get_desc();
|
385 |
}
|
386 |
|
387 |
+
$label = "$from {$this->arrow} $to";
|
|
|
|
|
388 |
|
389 |
+
$title = $this->get_field( 'title', 'from' );
|
390 |
|
391 |
if ( $title )
|
392 |
$label .= " ($title)";
|
395 |
}
|
396 |
}
|
397 |
|
398 |
+
|
399 |
+
class P2P_Indeterminate_Connection_Type extends P2P_Connection_Type {
|
400 |
+
|
401 |
+
protected $directed_class = 'P2P_Indeterminate_Directed_Connection_Type';
|
402 |
+
|
403 |
+
protected $arrow = '↔';
|
404 |
+
|
405 |
+
protected function choose_direction( $direction ) {
|
406 |
+
return 'from';
|
407 |
+
}
|
408 |
+
|
409 |
+
function _directions_for_admin( $direction, $show_ui ) {
|
410 |
+
return parent::_directions_for_admin( 'any', $show_ui );
|
411 |
+
}
|
412 |
+
}
|
413 |
+
|
414 |
+
|
415 |
+
class P2P_Reciprocal_Connection_Type extends P2P_Indeterminate_Connection_Type {
|
416 |
+
|
417 |
+
protected function choose_direction( $direction ) {
|
418 |
+
return 'any';
|
419 |
+
}
|
420 |
+
|
421 |
+
function _directions_for_admin( $direction, $show_ui ) {
|
422 |
+
if ( $show_ui )
|
423 |
+
$directions = array( 'any' );
|
424 |
+
else
|
425 |
+
$directions = array();
|
426 |
+
|
427 |
+
return $directions;
|
428 |
+
}
|
429 |
+
}
|
430 |
+
|
core/url-query.php
CHANGED
@@ -36,7 +36,7 @@ class P2P_URL_Query {
|
|
36 |
return;
|
37 |
|
38 |
_p2p_append( $query->query_vars, wp_array_slice_assoc( $_GET,
|
39 |
-
|
40 |
}
|
41 |
}
|
42 |
|
36 |
return;
|
37 |
|
38 |
_p2p_append( $query->query_vars, wp_array_slice_assoc( $_GET,
|
39 |
+
self::get_custom_qv() ) );
|
40 |
}
|
41 |
}
|
42 |
|
core/util.php
CHANGED
@@ -2,6 +2,9 @@
|
|
2 |
|
3 |
/** @internal */
|
4 |
function _p2p_expand_direction( $direction ) {
|
|
|
|
|
|
|
5 |
if ( 'any' == $direction )
|
6 |
return array( 'from', 'to' );
|
7 |
else
|
@@ -54,6 +57,18 @@ function _p2p_wrap( $items, $class ) {
|
|
54 |
return $items;
|
55 |
}
|
56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
/** @internal */
|
58 |
function _p2p_meta_sql_helper( $query ) {
|
59 |
global $wpdb;
|
2 |
|
3 |
/** @internal */
|
4 |
function _p2p_expand_direction( $direction ) {
|
5 |
+
if ( !$direction )
|
6 |
+
return array();
|
7 |
+
|
8 |
if ( 'any' == $direction )
|
9 |
return array( 'from', 'to' );
|
10 |
else
|
57 |
return $items;
|
58 |
}
|
59 |
|
60 |
+
/** @internal */
|
61 |
+
function _p2p_extract_post_types( $sides ) {
|
62 |
+
$ptypes = array();
|
63 |
+
|
64 |
+
foreach ( $sides as $side ) {
|
65 |
+
if ( 'post' == $side->get_object_type() )
|
66 |
+
_p2p_append( $ptypes, $side->query_vars['post_type'] );
|
67 |
+
}
|
68 |
+
|
69 |
+
return array_unique( $ptypes );
|
70 |
+
}
|
71 |
+
|
72 |
/** @internal */
|
73 |
function _p2p_meta_sql_helper( $query ) {
|
74 |
global $wpdb;
|
debug-utils.php
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Tools for testing and debugging P2P
|
4 |
+
|
5 |
+
add_action( 'p2p_registered_connection_type', '_p2p_register_missing_post_types' );
|
6 |
+
|
7 |
+
function _p2p_register_missing_post_types( $ctype ) {
|
8 |
+
foreach ( _p2p_extract_post_types( $ctype->side ) as $ptype ) {
|
9 |
+
if ( !post_type_exists( $ptype ) ) {
|
10 |
+
_p2p_generate_post_type( $ptype );
|
11 |
+
}
|
12 |
+
}
|
13 |
+
}
|
14 |
+
|
15 |
+
function _p2p_generate_post_type( $slug ) {
|
16 |
+
register_post_type( $slug, array(
|
17 |
+
'labels' => array(
|
18 |
+
'name' => ucfirst( $slug ),
|
19 |
+
'singular_name' => ucfirst( $slug ),
|
20 |
+
),
|
21 |
+
'public' => true,
|
22 |
+
'supports' => array( 'title' )
|
23 |
+
) );
|
24 |
+
}
|
25 |
+
|
26 |
+
function _p2p_walk( $posts, $level = 0 ) {
|
27 |
+
if ( 0 == $level )
|
28 |
+
echo "<pre>\n";
|
29 |
+
|
30 |
+
foreach ( $posts as $post ) {
|
31 |
+
echo str_repeat( "\t", $level ) . "$post->ID: $post->post_title\n";
|
32 |
+
|
33 |
+
if ( isset( $post->connected ) )
|
34 |
+
_p2p_walk( $post->connected, $level+1 );
|
35 |
+
}
|
36 |
+
|
37 |
+
if ( 0 == $level )
|
38 |
+
echo "</pre>\n";
|
39 |
+
}
|
40 |
+
|
lang/posts-to-posts-nl_NL.mo
CHANGED
Binary file
|
lang/posts-to-posts-nl_NL.po
CHANGED
@@ -1,18 +1,59 @@
|
|
1 |
-
# Translation of 1.4.
|
2 |
-
# This file is distributed under the same license as the 1.4.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
-
"PO-Revision-Date: 2012-09-
|
6 |
"MIME-Version: 1.0\n"
|
7 |
"Content-Type: text/plain; charset=UTF-8\n"
|
8 |
"Content-Transfer-Encoding: 8bit\n"
|
9 |
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
10 |
-
"X-Generator:
|
11 |
-
"Project-Id-Version: 1.4.
|
12 |
"POT-Creation-Date: \n"
|
13 |
"Last-Translator: Remco Tolsma <remco@pronamic.nl>\n"
|
14 |
"Language-Team: \n"
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
#: admin/box.php:38
|
17 |
msgid "Are you sure you want to delete all connections?"
|
18 |
msgstr "Weet je zeker dat je alle verbindingen wilt verwijderen?"
|
@@ -33,10 +74,6 @@ msgstr "volgende"
|
|
33 |
msgid "of"
|
34 |
msgstr "of"
|
35 |
|
36 |
-
#: admin/box.php:236
|
37 |
-
msgid "Can't create connection: %s"
|
38 |
-
msgstr "Kan verbinding niet maken: %s"
|
39 |
-
|
40 |
#: admin/factory.php:30
|
41 |
msgid " (from)"
|
42 |
msgstr "(van)"
|
@@ -53,46 +90,29 @@ msgstr "Verwijder alle verbindingen"
|
|
53 |
msgid "Delete connection"
|
54 |
msgstr "Verwijder verbinding"
|
55 |
|
56 |
-
#:
|
57 |
-
msgid "
|
58 |
-
msgstr "
|
59 |
-
|
60 |
-
#: admin/tools.php:41
|
61 |
-
msgid "<em>%s</em> is not a registered connection type."
|
62 |
-
msgstr "<em>%s</em> is niet een geregistreerde verbindingstype."
|
63 |
-
|
64 |
-
#: admin/tools.php:50
|
65 |
-
msgid "Converted %1$s connections from <em>%2$s</em> to <em>%3$s</em>."
|
66 |
-
msgstr "%1$s verbindingen omgezet van <em>%2$s</em> naar <em>%3$s</em>."
|
67 |
-
|
68 |
-
#: admin/tools.php:64
|
69 |
-
msgid "Name"
|
70 |
-
msgstr "Naam"
|
71 |
-
|
72 |
-
#: admin/tools.php:65
|
73 |
-
msgid "Information"
|
74 |
-
msgstr "Informatie"
|
75 |
|
76 |
-
#:
|
77 |
-
msgid "
|
78 |
-
msgstr "
|
79 |
|
80 |
-
#:
|
81 |
-
msgid "
|
82 |
-
msgstr "
|
83 |
|
84 |
-
#:
|
85 |
-
msgid "
|
86 |
-
msgstr ""
|
87 |
-
"Bekijk <a href=\"%s\">de wiki</a> om een verbindingstype te registeren."
|
88 |
|
89 |
-
#:
|
90 |
-
msgid "
|
91 |
-
msgstr "
|
92 |
|
93 |
-
#:
|
94 |
-
msgid "
|
95 |
-
msgstr "
|
96 |
|
97 |
#: core/extra.php:16
|
98 |
msgid "Posts 2 Posts"
|
@@ -112,7 +132,7 @@ msgstr "Verbindingstype:"
|
|
112 |
|
113 |
#: core/extra.php:46
|
114 |
msgid "Connection listing:"
|
115 |
-
msgstr "
|
116 |
|
117 |
#: core/extra.php:52
|
118 |
msgid "connected"
|
@@ -122,30 +142,6 @@ msgstr "verbonden"
|
|
122 |
msgid "related"
|
123 |
msgstr "gerelateerd"
|
124 |
|
125 |
-
#: core/side.php:220
|
126 |
-
msgid "Users"
|
127 |
-
msgstr "Gebruikers"
|
128 |
-
|
129 |
-
#: core/side.php:229
|
130 |
-
msgid "User"
|
131 |
-
msgstr "Gebruiker"
|
132 |
-
|
133 |
-
#: core/side.php:230
|
134 |
-
msgid "Search Users"
|
135 |
-
msgstr "Gebruikers zoeken"
|
136 |
-
|
137 |
-
#: core/side.php:231
|
138 |
-
msgid "No users found."
|
139 |
-
msgstr "Geen gebruikers gevonden."
|
140 |
-
|
141 |
-
#: core/type.php:79
|
142 |
-
msgid "Create connections"
|
143 |
-
msgstr "Verbindingen maken"
|
144 |
-
|
145 |
-
#: core/type.php:102
|
146 |
-
msgid "Connected %s"
|
147 |
-
msgstr "Verbonden %s"
|
148 |
-
|
149 |
#: scb/AdminPage.php:172
|
150 |
msgid "Settings <strong>saved</strong>."
|
151 |
msgstr "Instellingen <strong>opgeslagen</strong>."
|
1 |
+
# Translation of 1.4.3-alpha in Dutch
|
2 |
+
# This file is distributed under the same license as the 1.4.3-alpha package.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
+
"PO-Revision-Date: 2012-09-19 09:35+0100\n"
|
6 |
"MIME-Version: 1.0\n"
|
7 |
"Content-Type: text/plain; charset=UTF-8\n"
|
8 |
"Content-Transfer-Encoding: 8bit\n"
|
9 |
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
10 |
+
"X-Generator: Poedit 1.5.3\n"
|
11 |
+
"Project-Id-Version: 1.4.3-alpha\n"
|
12 |
"POT-Creation-Date: \n"
|
13 |
"Last-Translator: Remco Tolsma <remco@pronamic.nl>\n"
|
14 |
"Language-Team: \n"
|
15 |
|
16 |
+
#: admin/tools.php:7
|
17 |
+
msgid "Connection Types"
|
18 |
+
msgstr "Verbindingstypen"
|
19 |
+
|
20 |
+
#: admin/tools.php:41
|
21 |
+
msgid "<em>%s</em> is not a registered connection type."
|
22 |
+
msgstr "<em>%s</em> is niet een geregistreerde verbindingstype."
|
23 |
+
|
24 |
+
#: admin/tools.php:50
|
25 |
+
msgid "Converted %1$s connections from <em>%2$s</em> to <em>%3$s</em>."
|
26 |
+
msgstr "%1$s verbindingen omgezet van <em>%2$s</em> naar <em>%3$s</em>."
|
27 |
+
|
28 |
+
#: admin/tools.php:64
|
29 |
+
msgid "Name"
|
30 |
+
msgstr "Naam"
|
31 |
+
|
32 |
+
#: admin/tools.php:65
|
33 |
+
msgid "Information"
|
34 |
+
msgstr "Informatie"
|
35 |
+
|
36 |
+
#: admin/tools.php:66
|
37 |
+
msgid "Connections"
|
38 |
+
msgstr "Verbindingen"
|
39 |
+
|
40 |
+
#: admin/tools.php:74
|
41 |
+
msgid "No connection types registered."
|
42 |
+
msgstr "Geen verbindingstypen geregistreerd."
|
43 |
+
|
44 |
+
#: admin/tools.php:76
|
45 |
+
msgid "To register a connection type, see <a href=\"%s\">the wiki</a>."
|
46 |
+
msgstr ""
|
47 |
+
"Bekijk <a href=\"%s\">de wiki</a> om een verbindingstype te registeren."
|
48 |
+
|
49 |
+
#: admin/tools.php:93
|
50 |
+
msgid "Convert to registered connection type:"
|
51 |
+
msgstr "Omzetten naar geregistreerde verbindingstype:"
|
52 |
+
|
53 |
+
#: admin/tools.php:129
|
54 |
+
msgid "Go"
|
55 |
+
msgstr "Ga"
|
56 |
+
|
57 |
#: admin/box.php:38
|
58 |
msgid "Are you sure you want to delete all connections?"
|
59 |
msgstr "Weet je zeker dat je alle verbindingen wilt verwijderen?"
|
74 |
msgid "of"
|
75 |
msgstr "of"
|
76 |
|
|
|
|
|
|
|
|
|
77 |
#: admin/factory.php:30
|
78 |
msgid " (from)"
|
79 |
msgstr "(van)"
|
90 |
msgid "Delete connection"
|
91 |
msgstr "Verwijder verbinding"
|
92 |
|
93 |
+
#: core/type.php:85
|
94 |
+
msgid "Create connections"
|
95 |
+
msgstr "Verbindingen maken"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
+
#: core/type.php:108
|
98 |
+
msgid "Connected %s"
|
99 |
+
msgstr "Verbonden %s"
|
100 |
|
101 |
+
#: core/side.php:224
|
102 |
+
msgid "Users"
|
103 |
+
msgstr "Gebruikers"
|
104 |
|
105 |
+
#: core/side.php:233
|
106 |
+
msgid "User"
|
107 |
+
msgstr "Gebruiker"
|
|
|
108 |
|
109 |
+
#: core/side.php:234
|
110 |
+
msgid "Search Users"
|
111 |
+
msgstr "Gebruikers zoeken"
|
112 |
|
113 |
+
#: core/side.php:235
|
114 |
+
msgid "No users found."
|
115 |
+
msgstr "Geen gebruikers gevonden."
|
116 |
|
117 |
#: core/extra.php:16
|
118 |
msgid "Posts 2 Posts"
|
132 |
|
133 |
#: core/extra.php:46
|
134 |
msgid "Connection listing:"
|
135 |
+
msgstr "Verbindingslijst:"
|
136 |
|
137 |
#: core/extra.php:52
|
138 |
msgid "connected"
|
142 |
msgid "related"
|
143 |
msgstr "gerelateerd"
|
144 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
145 |
#: scb/AdminPage.php:172
|
146 |
msgid "Settings <strong>saved</strong>."
|
147 |
msgstr "Instellingen <strong>opgeslagen</strong>."
|
posts-to-posts.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
/*
|
3 |
Plugin Name: Posts 2 Posts
|
4 |
Description: Create many-to-many relationships between all types of posts.
|
5 |
-
Version: 1.4.
|
6 |
Author: scribu
|
7 |
Author URI: http://scribu.net/
|
8 |
Plugin URI: http://scribu.net/wordpress/posts-to-posts
|
@@ -10,7 +10,7 @@ Text Domain: posts-to-posts
|
|
10 |
Domain Path: /lang
|
11 |
*/
|
12 |
|
13 |
-
define( 'P2P_PLUGIN_VERSION', '1.4' );
|
14 |
|
15 |
define( 'P2P_TEXTDOMAIN', 'posts-to-posts' );
|
16 |
|
2 |
/*
|
3 |
Plugin Name: Posts 2 Posts
|
4 |
Description: Create many-to-many relationships between all types of posts.
|
5 |
+
Version: 1.4.3
|
6 |
Author: scribu
|
7 |
Author URI: http://scribu.net/
|
8 |
Plugin URI: http://scribu.net/wordpress/posts-to-posts
|
10 |
Domain Path: /lang
|
11 |
*/
|
12 |
|
13 |
+
define( 'P2P_PLUGIN_VERSION', '1.4.3' );
|
14 |
|
15 |
define( 'P2P_TEXTDOMAIN', 'posts-to-posts' );
|
16 |
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: scribu, ciobi
|
3 |
Tags: connections, custom post types, relationships, many-to-many, users
|
4 |
Requires at least: 3.4
|
5 |
-
Tested up to: 3.
|
6 |
-
Stable tag: 1.4.
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
@@ -31,7 +31,7 @@ Links: [**Documentation**](http://github.com/scribu/wp-posts-to-posts/wiki) | [P
|
|
31 |
See [Installing Plugins](http://codex.wordpress.org/Managing_Plugins#Installing_Plugins).
|
32 |
|
33 |
After activating it, refer to the [Basic usage](https://github.com/scribu/wp-posts-to-posts/wiki/Basic-usage) tutorial.
|
34 |
-
|
35 |
Additional info can be found on the [wiki](http://github.com/scribu/wp-posts-to-posts/wiki).
|
36 |
|
37 |
== Frequently Asked Questions ==
|
@@ -53,6 +53,12 @@ Make sure your host is running PHP 5. The only foolproof way to do this is to ad
|
|
53 |
|
54 |
== Changelog ==
|
55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
= 1.4.2 =
|
57 |
* fixed each_connected() returning wrapped objects
|
58 |
* fixed issue with user queries and get_current_screen()
|
2 |
Contributors: scribu, ciobi
|
3 |
Tags: connections, custom post types, relationships, many-to-many, users
|
4 |
Requires at least: 3.4
|
5 |
+
Tested up to: 3.5
|
6 |
+
Stable tag: 1.4.3
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
9 |
|
31 |
See [Installing Plugins](http://codex.wordpress.org/Managing_Plugins#Installing_Plugins).
|
32 |
|
33 |
After activating it, refer to the [Basic usage](https://github.com/scribu/wp-posts-to-posts/wiki/Basic-usage) tutorial.
|
34 |
+
|
35 |
Additional info can be found on the [wiki](http://github.com/scribu/wp-posts-to-posts/wiki).
|
36 |
|
37 |
== Frequently Asked Questions ==
|
53 |
|
54 |
== Changelog ==
|
55 |
|
56 |
+
= 1.4.3 =
|
57 |
+
* various bug fixes
|
58 |
+
* added 'inline' mode for shortcodes
|
59 |
+
* replaced 'trash' icon with 'minus' icon
|
60 |
+
* pass direction to 'default_cb'
|
61 |
+
|
62 |
= 1.4.2 =
|
63 |
* fixed each_connected() returning wrapped objects
|
64 |
* fixed issue with user queries and get_current_screen()
|
screenshot-1.png
DELETED
Binary file
|
screenshot-2.png
DELETED
Binary file
|
screenshot-3.png
DELETED
Binary file
|
screenshot-4.png
DELETED
Binary file
|
screenshot-5.png
DELETED
Binary file
|