Version Description
- improved UI
- added 'fields', 'context' and 'prevent_duplicates' args to p2p_register_connection_type()
- more info
Download this release
Release Info
Developer | scribu |
Plugin | Posts 2 Posts |
Version | 0.7 |
Comparing to | |
See all releases |
Code changes from version 0.6 to 0.7
- api.php +32 -27
- lang/posts-to-posts-ro_RO.mo +0 -0
- lang/posts-to-posts-ro_RO.po +53 -17
- lang/posts-to-posts.pot +39 -16
- posts-to-posts.php +1 -2
- readme.txt +15 -14
- screenshot-1.png +0 -0
- screenshot-2.png +0 -0
- storage.php +28 -10
- tests.php +51 -17
- ui/boxes.php +183 -88
- ui/images/add.png +0 -0
- ui/images/delete.png +0 -0
- ui/ui.css +168 -0
- ui/ui.js +228 -47
- ui/ui.php +103 -87
api.php
CHANGED
@@ -5,10 +5,13 @@
|
|
5 |
* This creates the appropriate meta box in the admin edit screen
|
6 |
*
|
7 |
* @param array $args Can be:
|
8 |
-
* - 'from' string
|
9 |
-
* - 'to' string
|
10 |
-
* - '
|
11 |
-
* - '
|
|
|
|
|
|
|
12 |
* - 'box' string A class that handles displaying and saving connections. Default: P2P_Box_Multiple
|
13 |
*/
|
14 |
function p2p_register_connection_type( $args ) {
|
@@ -16,20 +19,27 @@ function p2p_register_connection_type( $args ) {
|
|
16 |
|
17 |
if ( count( $argv ) > 1 ) {
|
18 |
$args = array();
|
19 |
-
list( $args['from'], $args['to'], $args['reciprocal'] ) = $argv;
|
20 |
}
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
}
|
30 |
|
31 |
/**
|
32 |
-
* Connect a post to one or more other posts
|
33 |
*
|
34 |
* @param int|array $from The first end of the connection
|
35 |
* @param int|array $to The second end of the connection
|
@@ -44,7 +54,7 @@ function p2p_connect( $from, $to, $data = array() ) {
|
|
44 |
}
|
45 |
|
46 |
/**
|
47 |
-
* Disconnect a post from or more other posts
|
48 |
*
|
49 |
* @param int|array $from The first end of the connection
|
50 |
* @param int|array|string $to The second end of the connection
|
@@ -59,7 +69,9 @@ function p2p_disconnect( $from, $to, $data = array() ) {
|
|
59 |
}
|
60 |
|
61 |
/**
|
62 |
-
* Get a list of connected posts
|
|
|
|
|
63 |
*
|
64 |
* @param int $post_id One end of the connection
|
65 |
* @param string $direction The direction of the connection. Can be 'to', 'from' or 'any'
|
@@ -68,17 +80,6 @@ function p2p_disconnect( $from, $to, $data = array() ) {
|
|
68 |
* @return array( p2p_id => post_id )
|
69 |
*/
|
70 |
function p2p_get_connected( $post_id, $direction = 'any', $data = array() ) {
|
71 |
-
if ( 'any' == $direction ) {
|
72 |
-
$from = P2P_Connections::get( $post_id, 'from', $data );
|
73 |
-
$to = P2P_Connections::get( $post_id, 'to', $data );
|
74 |
-
|
75 |
-
foreach ( $to as $p2p_id => $post_id ) {
|
76 |
-
$from[ $p2p_id ] = $post_id;
|
77 |
-
}
|
78 |
-
|
79 |
-
return $from;
|
80 |
-
}
|
81 |
-
|
82 |
return P2P_Connections::get( $post_id, $direction, $data );
|
83 |
}
|
84 |
|
@@ -242,7 +243,10 @@ class P2P_Query {
|
|
242 |
if ( !$found )
|
243 |
return $the_posts;
|
244 |
|
245 |
-
list( $search, $
|
|
|
|
|
|
|
246 |
|
247 |
p2p_each_connected( $direction, $key, $search, $wp_query );
|
248 |
|
@@ -251,6 +255,7 @@ class P2P_Query {
|
|
251 |
|
252 |
private function find_qv( $wp_query, $prefix = '' ) {
|
253 |
foreach ( self::$qv_map as $qv => $direction ) {
|
|
|
254 |
$search = $wp_query->get( $prefix . $qv );
|
255 |
if ( !empty( $search ) )
|
256 |
break;
|
5 |
* This creates the appropriate meta box in the admin edit screen
|
6 |
*
|
7 |
* @param array $args Can be:
|
8 |
+
* - 'from' string The first end of the connection.
|
9 |
+
* - 'to' string The second end of the connection.
|
10 |
+
* - 'fields' array Additional metadata fields (optional).
|
11 |
+
* - 'prevent_duplicates' bool Wether to disallow duplicate connections between the same two posts. Default: true.
|
12 |
+
* - 'reciprocal' bool Wether to show the box on both sides of the connection. Default: false.
|
13 |
+
* - 'title' string The box's title. Default: 'Connected {$post_type}s'
|
14 |
+
* - 'context' string Where should the box show up by default. Possible values: 'advanced' or 'side'
|
15 |
* - 'box' string A class that handles displaying and saving connections. Default: P2P_Box_Multiple
|
16 |
*/
|
17 |
function p2p_register_connection_type( $args ) {
|
19 |
|
20 |
if ( count( $argv ) > 1 ) {
|
21 |
$args = array();
|
22 |
+
@list( $args['from'], $args['to'], $args['reciprocal'] ) = $argv;
|
23 |
}
|
24 |
|
25 |
+
$defaults = array(
|
26 |
+
'from' => '',
|
27 |
+
'to' => '',
|
28 |
+
'fields' => array(),
|
29 |
+
'prevent_duplicates' => true,
|
30 |
+
'reciprocal' => false,
|
31 |
+
'title' => '',
|
32 |
+
'context' => 'side',
|
33 |
+
'box' => 'P2P_Box_Multiple',
|
34 |
+
);
|
35 |
+
|
36 |
+
$args = wp_parse_args( $args, $defaults );
|
37 |
+
|
38 |
+
P2P_Connection_Types::register( $args );
|
39 |
}
|
40 |
|
41 |
/**
|
42 |
+
* Connect a post to one or more other posts.
|
43 |
*
|
44 |
* @param int|array $from The first end of the connection
|
45 |
* @param int|array $to The second end of the connection
|
54 |
}
|
55 |
|
56 |
/**
|
57 |
+
* Disconnect a post from or more other posts.
|
58 |
*
|
59 |
* @param int|array $from The first end of the connection
|
60 |
* @param int|array|string $to The second end of the connection
|
69 |
}
|
70 |
|
71 |
/**
|
72 |
+
* Get a list of connected posts.
|
73 |
+
*
|
74 |
+
* Low-level function. Use new WP_Query( array( 'connected' => $post_id ) ) instead.
|
75 |
*
|
76 |
* @param int $post_id One end of the connection
|
77 |
* @param string $direction The direction of the connection. Can be 'to', 'from' or 'any'
|
80 |
* @return array( p2p_id => post_id )
|
81 |
*/
|
82 |
function p2p_get_connected( $post_id, $direction = 'any', $data = array() ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
return P2P_Connections::get( $post_id, $direction, $data );
|
84 |
}
|
85 |
|
243 |
if ( !$found )
|
244 |
return $the_posts;
|
245 |
|
246 |
+
list( $search, $qv, $direction ) = $found;
|
247 |
+
|
248 |
+
$qv = explode('_', $qv);
|
249 |
+
$key = isset( $qv[1] ) ? $qv[1] : '';
|
250 |
|
251 |
p2p_each_connected( $direction, $key, $search, $wp_query );
|
252 |
|
255 |
|
256 |
private function find_qv( $wp_query, $prefix = '' ) {
|
257 |
foreach ( self::$qv_map as $qv => $direction ) {
|
258 |
+
|
259 |
$search = $wp_query->get( $prefix . $qv );
|
260 |
if ( !empty( $search ) )
|
261 |
break;
|
lang/posts-to-posts-ro_RO.mo
CHANGED
Binary file
|
lang/posts-to-posts-ro_RO.po
CHANGED
@@ -7,9 +7,9 @@ msgid ""
|
|
7 |
msgstr ""
|
8 |
"Project-Id-Version: Posts 2 Posts 0.3\n"
|
9 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/posts-to-posts\n"
|
10 |
-
"POT-Creation-Date:
|
11 |
-
"PO-Revision-Date:
|
12 |
-
"Last-Translator: scribu <scribu
|
13 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
14 |
"Language: \n"
|
15 |
"MIME-Version: 1.0\n"
|
@@ -29,21 +29,49 @@ msgstr "Salvează schimbările"
|
|
29 |
msgid "Settings"
|
30 |
msgstr "Setări"
|
31 |
|
32 |
-
#: ui/boxes.php:
|
33 |
-
msgid "
|
34 |
-
msgstr "
|
35 |
|
36 |
-
#: ui/boxes.php:
|
37 |
-
msgid "
|
38 |
-
msgstr "
|
39 |
|
40 |
-
#: ui/boxes.php:
|
41 |
-
msgid "
|
42 |
-
msgstr "
|
43 |
|
44 |
-
#: ui/boxes.php:
|
45 |
-
msgid "
|
46 |
-
msgstr "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
#. Plugin Name of the plugin/theme
|
49 |
msgid "Posts 2 Posts"
|
@@ -65,6 +93,14 @@ msgstr ""
|
|
65 |
msgid "http://scribu.net/"
|
66 |
msgstr ""
|
67 |
|
68 |
-
#~ msgid "
|
69 |
-
#~ msgstr "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
|
7 |
msgstr ""
|
8 |
"Project-Id-Version: Posts 2 Posts 0.3\n"
|
9 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/posts-to-posts\n"
|
10 |
+
"POT-Creation-Date: 2011-03-30 21:56+0300\n"
|
11 |
+
"PO-Revision-Date: 2011-03-30 21:56+0200\n"
|
12 |
+
"Last-Translator: scribu <mail@scribu.net>\n"
|
13 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
14 |
"Language: \n"
|
15 |
"MIME-Version: 1.0\n"
|
29 |
msgid "Settings"
|
30 |
msgstr "Setări"
|
31 |
|
32 |
+
#: ui/boxes.php:88
|
33 |
+
msgid "Create connections:"
|
34 |
+
msgstr "Creează conexiuni:"
|
35 |
|
36 |
+
#: ui/boxes.php:108
|
37 |
+
msgid "Previous"
|
38 |
+
msgstr "Anterioare"
|
39 |
|
40 |
+
#: ui/boxes.php:109
|
41 |
+
msgid "of"
|
42 |
+
msgstr "din"
|
43 |
|
44 |
+
#: ui/boxes.php:110
|
45 |
+
msgid "Next"
|
46 |
+
msgstr "Următoare"
|
47 |
+
|
48 |
+
#: ui/boxes.php:114
|
49 |
+
msgid "Recent"
|
50 |
+
msgstr "Recente"
|
51 |
+
|
52 |
+
#: ui/boxes.php:174
|
53 |
+
#: ui/boxes.php:175
|
54 |
+
msgid "Create connection"
|
55 |
+
msgstr "Crează conexiune"
|
56 |
+
|
57 |
+
#: ui/boxes.php:182
|
58 |
+
#: ui/boxes.php:183
|
59 |
+
msgid "Delete connection"
|
60 |
+
msgstr "Șterge conexiune"
|
61 |
+
|
62 |
+
#: ui/boxes.php:189
|
63 |
+
#: ui/boxes.php:190
|
64 |
+
msgid "Delete all connections"
|
65 |
+
msgstr "Șterge toate conexiunile"
|
66 |
+
|
67 |
+
#: ui/ui.php:40
|
68 |
+
#, php-format
|
69 |
+
msgid "Connected %s"
|
70 |
+
msgstr "%s conectate"
|
71 |
+
|
72 |
+
#: ui/ui.php:87
|
73 |
+
msgid "Are you sure you want to delete all connections?"
|
74 |
+
msgstr "Sigur vreți să ștergeți toate conexiunile?"
|
75 |
|
76 |
#. Plugin Name of the plugin/theme
|
77 |
msgid "Posts 2 Posts"
|
93 |
msgid "http://scribu.net/"
|
94 |
msgstr ""
|
95 |
|
96 |
+
#~ msgid "Search"
|
97 |
+
#~ msgstr "Căutare"
|
98 |
+
#~ msgid ""
|
99 |
+
#~ "Start typing the title of a post you want to connect and then click on to "
|
100 |
+
#~ "connect it."
|
101 |
+
#~ msgstr ""
|
102 |
+
#~ "Începe să scrii titlul post-ului de conectat și apoi fă click pentru a-l "
|
103 |
+
#~ "conecta."
|
104 |
+
#~ msgid "Enter IDs of posts to connect, separated by commas."
|
105 |
+
#~ msgstr "Intrdu ID-uri ale post-urilor de conectat, separate prin virgulă."
|
106 |
|
lang/posts-to-posts.pot
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
# Translation of the WordPress plugin Posts 2 Posts 0.
|
2 |
-
# Copyright (C)
|
3 |
# This file is distributed under the same license as the Posts 2 Posts package.
|
4 |
-
# FIRST AUTHOR <EMAIL@ADDRESS>,
|
5 |
#
|
6 |
#, fuzzy
|
7 |
msgid ""
|
8 |
msgstr ""
|
9 |
-
"Project-Id-Version: Posts 2 Posts 0.
|
10 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/posts-to-posts\n"
|
11 |
-
"POT-Creation-Date:
|
12 |
-
"PO-Revision-Date:
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
15 |
"Language: \n"
|
@@ -29,22 +29,45 @@ msgstr ""
|
|
29 |
msgid "Settings"
|
30 |
msgstr ""
|
31 |
|
32 |
-
#: ui/boxes.php:
|
33 |
-
msgid "
|
34 |
msgstr ""
|
35 |
|
36 |
-
#: ui/boxes.php:
|
37 |
-
msgid "
|
38 |
msgstr ""
|
39 |
|
40 |
-
#: ui/boxes.php:
|
41 |
-
msgid ""
|
42 |
-
|
43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
msgstr ""
|
45 |
|
46 |
-
#: ui/
|
47 |
-
msgid "
|
48 |
msgstr ""
|
49 |
|
50 |
#. Plugin Name of the plugin/theme
|
1 |
+
# Translation of the WordPress plugin Posts 2 Posts 0.7-beta by scribu.
|
2 |
+
# Copyright (C) 2011 scribu
|
3 |
# This file is distributed under the same license as the Posts 2 Posts package.
|
4 |
+
# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
|
5 |
#
|
6 |
#, fuzzy
|
7 |
msgid ""
|
8 |
msgstr ""
|
9 |
+
"Project-Id-Version: Posts 2 Posts 0.7-beta\n"
|
10 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/posts-to-posts\n"
|
11 |
+
"POT-Creation-Date: 2011-03-30 21:56+0300\n"
|
12 |
+
"PO-Revision-Date: 2011-MO-DA HO:MI+ZONE\n"
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
15 |
"Language: \n"
|
29 |
msgid "Settings"
|
30 |
msgstr ""
|
31 |
|
32 |
+
#: ui/boxes.php:88
|
33 |
+
msgid "Create connections:"
|
34 |
msgstr ""
|
35 |
|
36 |
+
#: ui/boxes.php:108
|
37 |
+
msgid "Previous"
|
38 |
msgstr ""
|
39 |
|
40 |
+
#: ui/boxes.php:109
|
41 |
+
msgid "of"
|
42 |
+
msgstr ""
|
43 |
+
|
44 |
+
#: ui/boxes.php:110
|
45 |
+
msgid "Next"
|
46 |
+
msgstr ""
|
47 |
+
|
48 |
+
#: ui/boxes.php:114
|
49 |
+
msgid "Recent"
|
50 |
+
msgstr ""
|
51 |
+
|
52 |
+
#: ui/boxes.php:174 ui/boxes.php:175
|
53 |
+
msgid "Create connection"
|
54 |
+
msgstr ""
|
55 |
+
|
56 |
+
#: ui/boxes.php:182 ui/boxes.php:183
|
57 |
+
msgid "Delete connection"
|
58 |
+
msgstr ""
|
59 |
+
|
60 |
+
#: ui/boxes.php:189 ui/boxes.php:190
|
61 |
+
msgid "Delete all connections"
|
62 |
+
msgstr ""
|
63 |
+
|
64 |
+
#: ui/ui.php:40
|
65 |
+
#, php-format
|
66 |
+
msgid "Connected %s"
|
67 |
msgstr ""
|
68 |
|
69 |
+
#: ui/ui.php:87
|
70 |
+
msgid "Are you sure you want to delete all connections?"
|
71 |
msgstr ""
|
72 |
|
73 |
#. Plugin Name of the plugin/theme
|
posts-to-posts.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: Posts 2 Posts
|
4 |
-
Version: 0.
|
5 |
Plugin Author: scribu
|
6 |
Description: Create many-to-many relationships between all types of posts
|
7 |
Author URI: http://scribu.net/
|
@@ -39,7 +39,6 @@ function _p2p_init() {
|
|
39 |
P2P_Connections::init( __FILE__ );
|
40 |
P2P_Query::init();
|
41 |
P2P_Connection_Types::init();
|
42 |
-
P2P_Box_Multiple::init();
|
43 |
|
44 |
P2P_Migrate::init();
|
45 |
}
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: Posts 2 Posts
|
4 |
+
Version: 0.7
|
5 |
Plugin Author: scribu
|
6 |
Description: Create many-to-many relationships between all types of posts
|
7 |
Author URI: http://scribu.net/
|
39 |
P2P_Connections::init( __FILE__ );
|
40 |
P2P_Query::init();
|
41 |
P2P_Connection_Types::init();
|
|
|
42 |
|
43 |
P2P_Migrate::init();
|
44 |
}
|
readme.txt
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
=== Posts 2 Posts ===
|
2 |
-
Contributors: scribu
|
3 |
Donate link: http://scribu.net/paypal
|
4 |
Tags: cms, custom post types, relationships, many-to-many
|
5 |
Requires at least: 3.0
|
6 |
Tested up to: 3.1
|
7 |
-
Stable tag: 0.
|
8 |
|
9 |
Create connections between posts
|
10 |
|
@@ -12,20 +12,15 @@ Create connections between posts
|
|
12 |
|
13 |
This plugin allows you to create many-to-many relationships between posts of all types.
|
14 |
|
15 |
-
|
16 |
|
17 |
-
|
18 |
-
function my_connection_types() {
|
19 |
-
if ( !function_exists('p2p_register_connection_type') )
|
20 |
-
return;
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
`
|
26 |
-
<br>
|
27 |
|
28 |
-
Links: [
|
29 |
|
30 |
== Installation ==
|
31 |
|
@@ -45,10 +40,16 @@ Make sure your host is running PHP 5. The only foolproof way to do this is to ad
|
|
45 |
|
46 |
== Screenshots ==
|
47 |
|
48 |
-
1.
|
|
|
49 |
|
50 |
== Changelog ==
|
51 |
|
|
|
|
|
|
|
|
|
|
|
52 |
= 0.6 =
|
53 |
* added p2p_each_connected()
|
54 |
* fixed p2p_is_connected()
|
1 |
=== Posts 2 Posts ===
|
2 |
+
Contributors: scribu, ciobi
|
3 |
Donate link: http://scribu.net/paypal
|
4 |
Tags: cms, custom post types, relationships, many-to-many
|
5 |
Requires at least: 3.0
|
6 |
Tested up to: 3.1
|
7 |
+
Stable tag: 0.7
|
8 |
|
9 |
Create connections between posts
|
10 |
|
12 |
|
13 |
This plugin allows you to create many-to-many relationships between posts of all types.
|
14 |
|
15 |
+
You can use it to manually create lists of related posts.
|
16 |
|
17 |
+
Or, if you have a 'product' post type, you can make a by-directional connection to a 'review' post type.
|
|
|
|
|
|
|
18 |
|
19 |
+
The possibilities are endless.
|
20 |
+
|
21 |
+
Head out to the [Wiki](https://github.com/scribu/wp-posts-to-posts/wiki) for tutorials and other resources.
|
|
|
|
|
22 |
|
23 |
+
Links: [Plugin News](http://scribu.net/wordpress/posts-to-posts) | [Author's Site](http://scribu.net)
|
24 |
|
25 |
== Installation ==
|
26 |
|
40 |
|
41 |
== Screenshots ==
|
42 |
|
43 |
+
1. Simple connection metabox
|
44 |
+
2. Advanced connection metabox
|
45 |
|
46 |
== Changelog ==
|
47 |
|
48 |
+
= 0.7 =
|
49 |
+
* improved UI
|
50 |
+
* added 'fields', 'context' and 'prevent_duplicates' args to p2p_register_connection_type()
|
51 |
+
* [more info](http://scribu.net/wordpress/posts-to-posts/p2p-0-7.html)
|
52 |
+
|
53 |
= 0.6 =
|
54 |
* added p2p_each_connected()
|
55 |
* fixed p2p_is_connected()
|
screenshot-1.png
CHANGED
Binary file
|
screenshot-2.png
ADDED
Binary file
|
storage.php
CHANGED
@@ -44,20 +44,36 @@ class P2P_Connections {
|
|
44 |
* @return array( p2p_id => post_id ) if $to is string
|
45 |
* @return array( p2p_id ) if $to is int
|
46 |
*/
|
47 |
-
function get( $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
global $wpdb;
|
49 |
|
50 |
$fields = "$wpdb->p2p.p2p_id";
|
51 |
$where = '';
|
52 |
$join = '';
|
53 |
|
|
|
54 |
switch ( $to ) {
|
55 |
case 'from':
|
56 |
-
$fields .=
|
57 |
$where .= $wpdb->prepare( "p2p_from = %d", $from );
|
58 |
break;
|
59 |
case 'to':
|
60 |
-
$fields .=
|
61 |
$where .= $wpdb->prepare( "p2p_to = %d", $from );
|
62 |
break;
|
63 |
default:
|
@@ -91,10 +107,11 @@ class P2P_Connections {
|
|
91 |
* @param int $from post id
|
92 |
* @param int $to post id
|
93 |
* @param array $data additional data about the connection
|
|
|
94 |
*
|
95 |
* @return int|bool connection id or False on failure
|
96 |
*/
|
97 |
-
function connect( $from, $to, $data = array() ) {
|
98 |
global $wpdb;
|
99 |
|
100 |
$from = absint( $from );
|
@@ -103,11 +120,6 @@ class P2P_Connections {
|
|
103 |
if ( !$from || !$to )
|
104 |
return false;
|
105 |
|
106 |
-
$p2p_ids = self::get( $from, $to, $data, true );
|
107 |
-
|
108 |
-
if ( !empty( $p2p_ids ) )
|
109 |
-
return $p2p_ids[0];
|
110 |
-
|
111 |
$wpdb->insert( $wpdb->p2p, array( 'p2p_from' => $from, 'p2p_to' => $to ), '%d' );
|
112 |
|
113 |
$p2p_id = $wpdb->insert_id;
|
@@ -128,7 +140,13 @@ class P2P_Connections {
|
|
128 |
* @return int Number of connections deleted
|
129 |
*/
|
130 |
function disconnect( $from, $to, $data = array() ) {
|
131 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
}
|
133 |
|
134 |
/**
|
44 |
* @return array( p2p_id => post_id ) if $to is string
|
45 |
* @return array( p2p_id ) if $to is int
|
46 |
*/
|
47 |
+
function get( $post_id, $direction, $data = array() ) {
|
48 |
+
if ( 'any' == $direction ) {
|
49 |
+
$from = self::_get( $post_id, 'from', $data );
|
50 |
+
$to = self::_get( $post_id, 'to', $data );
|
51 |
+
|
52 |
+
foreach ( $to as $p2p_id => $post_id ) {
|
53 |
+
$from[ $p2p_id ] = $post_id;
|
54 |
+
}
|
55 |
+
|
56 |
+
return $from;
|
57 |
+
}
|
58 |
+
|
59 |
+
return self::_get( $post_id, $direction, $data );
|
60 |
+
}
|
61 |
+
|
62 |
+
private function _get( $from, $to, $data = array() ) {
|
63 |
global $wpdb;
|
64 |
|
65 |
$fields = "$wpdb->p2p.p2p_id";
|
66 |
$where = '';
|
67 |
$join = '';
|
68 |
|
69 |
+
$_return_p2p_ids = false;
|
70 |
switch ( $to ) {
|
71 |
case 'from':
|
72 |
+
$fields .= ', p2p_to AS post_id';
|
73 |
$where .= $wpdb->prepare( "p2p_from = %d", $from );
|
74 |
break;
|
75 |
case 'to':
|
76 |
+
$fields .= ', p2p_from AS post_id';
|
77 |
$where .= $wpdb->prepare( "p2p_to = %d", $from );
|
78 |
break;
|
79 |
default:
|
107 |
* @param int $from post id
|
108 |
* @param int $to post id
|
109 |
* @param array $data additional data about the connection
|
110 |
+
* @param string $duplicates Duplicate prevention strategy: 'none', 'matching_data', 'strict'
|
111 |
*
|
112 |
* @return int|bool connection id or False on failure
|
113 |
*/
|
114 |
+
function connect( $from, $to, $data = array(), $duplicates = 'matching_data' ) {
|
115 |
global $wpdb;
|
116 |
|
117 |
$from = absint( $from );
|
120 |
if ( !$from || !$to )
|
121 |
return false;
|
122 |
|
|
|
|
|
|
|
|
|
|
|
123 |
$wpdb->insert( $wpdb->p2p, array( 'p2p_from' => $from, 'p2p_to' => $to ), '%d' );
|
124 |
|
125 |
$p2p_id = $wpdb->insert_id;
|
140 |
* @return int Number of connections deleted
|
141 |
*/
|
142 |
function disconnect( $from, $to, $data = array() ) {
|
143 |
+
$connections = self::get( $from, $to, $data );
|
144 |
+
|
145 |
+
// We're interested in the p2p_ids
|
146 |
+
if ( !(int) $to )
|
147 |
+
$connections = array_keys( $connections );
|
148 |
+
|
149 |
+
return self::delete( $connections );
|
150 |
}
|
151 |
|
152 |
/**
|
tests.php
CHANGED
@@ -15,12 +15,46 @@ class P2P_Test {
|
|
15 |
}
|
16 |
|
17 |
function _init() {
|
18 |
-
register_post_type('actor', array(
|
19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
|
21 |
-
|
22 |
-
|
23 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
}
|
25 |
|
26 |
function setup() {
|
@@ -134,18 +168,18 @@ class P2P_Test {
|
|
134 |
|
135 |
assert( 'array_intersect_assoc($r, $raw) == $r' );
|
136 |
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
|
150 |
# self::walk( $posts );
|
151 |
|
15 |
}
|
16 |
|
17 |
function _init() {
|
18 |
+
register_post_type('actor', array(
|
19 |
+
'public' => true,
|
20 |
+
'labels' => array(
|
21 |
+
'name' => 'Actors',
|
22 |
+
'singular_name' => 'Actor',
|
23 |
+
'search_items' => 'Search Actors',
|
24 |
+
'not_found' => 'No actors found.'
|
25 |
+
),
|
26 |
+
'has_archive' => 'actors'
|
27 |
+
));
|
28 |
+
register_post_type('movie', array(
|
29 |
+
'public' => true,
|
30 |
+
'labels' => array(
|
31 |
+
'name' => 'Movies',
|
32 |
+
'singular_name' => 'Movie',
|
33 |
+
'search_items' => 'Search movies',
|
34 |
+
'not_found' => 'No movies found.',
|
35 |
+
)
|
36 |
+
) );
|
37 |
+
|
38 |
+
p2p_register_connection_type( array(
|
39 |
+
'from' => 'actor',
|
40 |
+
'to' => 'actor',
|
41 |
+
'reciprocal' => true,
|
42 |
+
'title' => array( 'from' => 'Doubles', 'to' => 'Main Actor' )
|
43 |
+
) );
|
44 |
|
45 |
+
p2p_register_connection_type( array(
|
46 |
+
'from' => 'actor',
|
47 |
+
'to' => 'movie',
|
48 |
+
'reciprocal' => true,
|
49 |
+
'fields' => array(
|
50 |
+
'role' => 'Role',
|
51 |
+
'role_type' => 'Role Type'
|
52 |
+
),
|
53 |
+
'prevent_duplicates' => false,
|
54 |
+
'title' => array( 'from' => 'Played In', 'to' => 'Cast' ),
|
55 |
+
) );
|
56 |
+
|
57 |
+
p2p_register_connection_type('actor', 'post');
|
58 |
}
|
59 |
|
60 |
function setup() {
|
168 |
|
169 |
assert( 'array_intersect_assoc($r, $raw) == $r' );
|
170 |
|
171 |
+
// test 'each_*' query vars
|
172 |
+
$posts = get_posts( array(
|
173 |
+
'post_type' => 'actor',
|
174 |
+
'post_status' => 'any',
|
175 |
+
'nopaging' => true,
|
176 |
+
'each_connected' => array(
|
177 |
+
'post_type' => 'movie',
|
178 |
+
'post_status' => 'any',
|
179 |
+
'nopaging' => true,
|
180 |
+
),
|
181 |
+
'suppress_filters' => false
|
182 |
+
) );
|
183 |
|
184 |
# self::walk( $posts );
|
185 |
|
ui/boxes.php
CHANGED
@@ -2,115 +2,192 @@
|
|
2 |
|
3 |
class P2P_Box_Multiple extends P2P_Box {
|
4 |
|
5 |
-
|
|
|
6 |
|
7 |
-
|
8 |
-
|
9 |
-
|
|
|
|
|
10 |
}
|
11 |
|
12 |
-
function
|
13 |
-
|
|
|
14 |
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
}
|
23 |
|
24 |
-
function
|
25 |
-
|
26 |
-
p2p_delete_connection( array_diff( $data['all'], (array) @$data['enabled'] ) );
|
27 |
|
28 |
-
|
29 |
-
$meta = array();
|
30 |
-
foreach ( $this->meta_keys as $meta_key ) {
|
31 |
-
$meta_value = $data[ $meta_key ][ $i ];
|
32 |
|
33 |
-
|
34 |
-
|
35 |
|
36 |
-
|
37 |
-
|
|
|
38 |
|
39 |
-
|
40 |
-
p2p_connect( $post_b, $post_a, $meta );
|
41 |
-
else
|
42 |
-
p2p_connect( $post_a, $post_b, $meta );
|
43 |
-
}
|
44 |
}
|
45 |
|
46 |
function box( $post_id ) {
|
47 |
$connected_ids = $this->get_connected_ids( $post_id );
|
48 |
|
49 |
-
|
50 |
-
|
51 |
-
|
|
|
52 |
|
53 |
-
|
54 |
-
<div class="hide-if-no-js checkboxes">
|
55 |
-
<ul class="p2p_connected">
|
56 |
-
<?php if ( empty( $connected_ids ) ) { ?>
|
57 |
-
<li class="howto"><?php _e( 'No connections.', 'posts-to-posts' ); ?></li>
|
58 |
-
<?php } else {
|
59 |
-
foreach ( $connected_ids as $p2p_id => $post_b ) {
|
60 |
-
$this->connection_template( $post_b, $p2p_id );
|
61 |
-
}
|
62 |
-
} ?>
|
63 |
-
</ul>
|
64 |
-
|
65 |
-
<?php echo html( 'p class="p2p_search"',
|
66 |
-
scbForms::input( array(
|
67 |
-
'type' => 'text',
|
68 |
-
'name' => 'p2p_search_' . $this->to,
|
69 |
-
'desc' => __( 'Search', 'posts-to-posts' ) . ':',
|
70 |
-
'desc_pos' => 'before',
|
71 |
-
'extra' => array( 'autocomplete' => 'off' ),
|
72 |
-
) )
|
73 |
-
. '<img alt="" src="' . admin_url( 'images/wpspin_light.gif' ) . '" class="waiting" style="display: none;">'
|
74 |
-
); ?>
|
75 |
-
|
76 |
-
<ul class="p2p_results"></ul>
|
77 |
-
<p class="howto"><?php _e( 'Start typing the title of a post you want to connect and then click on to connect it.', 'posts-to-posts' ); ?></p>
|
78 |
-
</div>
|
79 |
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
</div>
|
89 |
|
90 |
-
|
91 |
-
|
92 |
-
|
|
|
|
|
93 |
</div>
|
94 |
</div>
|
|
|
|
|
95 |
<?php
|
96 |
}
|
97 |
|
98 |
-
function
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
$
|
103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
}
|
105 |
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
}
|
115 |
|
116 |
protected function get_connected_ids( $post_id ) {
|
@@ -132,18 +209,36 @@ class P2P_Box_Multiple extends P2P_Box {
|
|
132 |
return array_intersect( $connected_posts, $post_ids ); // to preserve p2p_id keys
|
133 |
}
|
134 |
|
135 |
-
function get_search_args( $
|
136 |
-
|
137 |
-
's' => $search,
|
138 |
'post_type' => $this->to,
|
139 |
'post_status' => 'any',
|
140 |
'posts_per_page' => 5,
|
141 |
-
'order' => 'ASC',
|
142 |
-
'orderby' => 'title',
|
143 |
'suppress_filters' => false,
|
144 |
'update_post_term_cache' => false,
|
145 |
'update_post_meta_cache' => false
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
);
|
|
|
|
|
|
|
|
|
|
|
147 |
}
|
148 |
}
|
149 |
|
2 |
|
3 |
class P2P_Box_Multiple extends P2P_Box {
|
4 |
|
5 |
+
function setup() {
|
6 |
+
$ptype_obj = get_post_type_object( $this->to );
|
7 |
|
8 |
+
$this->columns = array_merge(
|
9 |
+
array( 'delete' => $this->clear_connections_link() ),
|
10 |
+
array( 'title' => $ptype_obj->labels->singular_name ),
|
11 |
+
$this->fields
|
12 |
+
);
|
13 |
}
|
14 |
|
15 |
+
function connect() {
|
16 |
+
$from = absint( $_POST['from'] );
|
17 |
+
$to = absint( $_POST['to'] );
|
18 |
|
19 |
+
if ( !$from || !$to )
|
20 |
+
die(-1);
|
21 |
+
|
22 |
+
$args = array( $from, $to );
|
23 |
+
|
24 |
+
if ( $this->reversed )
|
25 |
+
$args = array_reverse( $args );
|
26 |
+
|
27 |
+
$p2p_id = false;
|
28 |
+
if ( $this->prevent_duplicates ) {
|
29 |
+
$p2p_ids = P2P_Connections::get( $args[0], $args[1] );
|
30 |
+
|
31 |
+
if ( !empty( $p2p_ids ) )
|
32 |
+
$p2p_id = $p2p_ids[0];
|
33 |
+
}
|
34 |
+
|
35 |
+
if ( !$p2p_id )
|
36 |
+
$p2p_id = P2P_Connections::connect( $args[0], $args[1] );
|
37 |
+
|
38 |
+
$this->connection_row( $p2p_id, $to );
|
39 |
}
|
40 |
|
41 |
+
function disconnect() {
|
42 |
+
$p2p_id = absint( $_POST['p2p_id'] );
|
|
|
43 |
|
44 |
+
p2p_delete_connection( $p2p_id );
|
|
|
|
|
|
|
45 |
|
46 |
+
die(1);
|
47 |
+
}
|
48 |
|
49 |
+
function clear_connections() {
|
50 |
+
$post_id = absint( $_POST['post_id'] );
|
51 |
+
p2p_disconnect( $post_id, $this->direction );
|
52 |
|
53 |
+
die(1);
|
|
|
|
|
|
|
|
|
54 |
}
|
55 |
|
56 |
function box( $post_id ) {
|
57 |
$connected_ids = $this->get_connected_ids( $post_id );
|
58 |
|
59 |
+
$data_attr = array();
|
60 |
+
foreach ( array( 'box_id', 'direction', 'prevent_duplicates' ) as $key )
|
61 |
+
$data_attr[] = "data-$key='" . $this->$key . "'";
|
62 |
+
$data_attr = implode( ' ', $data_attr );
|
63 |
|
64 |
+
?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
+
<div class="p2p-box">
|
67 |
+
<table class="p2p-connections" <?php if ( empty( $connected_ids ) ) echo 'style="display:none"'; ?>>
|
68 |
+
<thead>
|
69 |
+
<tr>
|
70 |
+
<?php
|
71 |
+
foreach ( $this->columns as $key => $title ) {
|
72 |
+
echo html( 'th', array( 'class' => "p2p-col-$key" ), $title );
|
73 |
+
}
|
74 |
+
?>
|
75 |
+
</tr>
|
76 |
+
</thead>
|
77 |
+
|
78 |
+
<tbody>
|
79 |
+
<?php
|
80 |
+
foreach ( $connected_ids as $p2p_id => $post_b ) {
|
81 |
+
$this->connection_row( $p2p_id, $post_b );
|
82 |
+
}
|
83 |
+
?>
|
84 |
+
</tbody>
|
85 |
+
</table>
|
86 |
+
|
87 |
+
<div class="p2p-add-new" <?php echo $data_attr; ?>>
|
88 |
+
<p><strong><?php _e( 'Create connections:', 'posts-to-posts' ); ?></strong></p>
|
89 |
+
|
90 |
+
<div class="p2p-search">
|
91 |
+
<?php echo html( 'input', array(
|
92 |
+
'type' => 'text',
|
93 |
+
'name' => 'p2p_search_' . $this->to,
|
94 |
+
'autocomplete' => 'off',
|
95 |
+
'placeholder' => get_post_type_object( $this->to )->labels->search_items
|
96 |
+
) ); ?>
|
97 |
+
</div>
|
98 |
+
|
99 |
+
<table class="p2p-results">
|
100 |
+
<tbody>
|
101 |
+
</tbody>
|
102 |
+
</table>
|
103 |
+
</div><!--.p2p-add-new-->
|
104 |
+
</div><!--.p2p-box-->
|
105 |
+
|
106 |
+
<div class="p2p-footer">
|
107 |
+
<div class="p2p-nav">
|
108 |
+
<div class="p2p-prev button" title="<?php _e( 'Previous', 'p2p-textdomain' ); ?>">‹</div>
|
109 |
+
<div><span class="p2p-current"></span> <? _e( 'of', 'p2p-textdomain' ); ?> <span class="p2p-total"></span></div>
|
110 |
+
<div class="p2p-next button" title="<?php _e( 'Next', 'p2p-textdomain' ); ?>">›</div>
|
111 |
</div>
|
112 |
|
113 |
+
<a href="#" class="p2p-recent button" name="p2p-recent">
|
114 |
+
<?php _e( 'Recent', 'posts-to-posts' ); ?>
|
115 |
+
</a>
|
116 |
+
<div class="clear">
|
117 |
+
<!-- Clearfix would be better -->
|
118 |
</div>
|
119 |
</div>
|
120 |
+
|
121 |
+
|
122 |
<?php
|
123 |
}
|
124 |
|
125 |
+
protected function connection_row( $p2p_id, $post_id ) {
|
126 |
+
echo '<tr>';
|
127 |
+
|
128 |
+
foreach ( array_keys( $this->columns ) as $key ) {
|
129 |
+
switch ( $key ) {
|
130 |
+
case 'title':
|
131 |
+
$value = $this->column_title( $post_id );
|
132 |
+
break;
|
133 |
+
|
134 |
+
case 'delete':
|
135 |
+
$value = $this->column_delete( $p2p_id );
|
136 |
+
break;
|
137 |
+
|
138 |
+
default:
|
139 |
+
$value = html( 'input', array(
|
140 |
+
'type' => 'text',
|
141 |
+
'name' => "p2p_meta[$p2p_id][$key]",
|
142 |
+
'value' => p2p_get_meta( $p2p_id, $key, true )
|
143 |
+
) );
|
144 |
+
}
|
145 |
+
|
146 |
+
echo html( 'td', array( 'class' => "p2p-col-$key" ), $value );
|
147 |
+
}
|
148 |
+
|
149 |
+
echo '</tr>';
|
150 |
+
}
|
151 |
+
|
152 |
+
public function results_row( $post ) {
|
153 |
+
echo '<tr>';
|
154 |
+
|
155 |
+
foreach ( array( 'add', 'title' ) as $key ) {
|
156 |
+
$method = "column_$key";
|
157 |
+
echo html( 'td', array( 'class' => "p2p-col-$key" ), $this->$method( $post->ID ) );
|
158 |
}
|
159 |
|
160 |
+
echo '</tr>';
|
161 |
+
}
|
162 |
+
|
163 |
+
protected function column_title( $post_id ) {
|
164 |
+
return html( 'a', array(
|
165 |
+
'href' => str_replace( '&', '&', get_edit_post_link( $post_id ) ),
|
166 |
+
'title' => get_post_type_object( get_post_type( $post_id ) )->labels->edit_item,
|
167 |
+
), get_post_field( 'post_title', $post_id ) );
|
168 |
+
}
|
169 |
+
|
170 |
+
protected function column_add( $post_id ) {
|
171 |
+
return html( 'a', array(
|
172 |
+
'data-post_id' => $post_id,
|
173 |
+
'href' => '#',
|
174 |
+
'title' => __( 'Create connection', 'posts-to-posts' )
|
175 |
+
), __( 'Create connection', 'posts-to-posts' ) );
|
176 |
+
}
|
177 |
+
|
178 |
+
protected function column_delete( $p2p_id ) {
|
179 |
+
return html( 'a', array(
|
180 |
+
'data-p2p_id' => $p2p_id,
|
181 |
+
'href' => '#',
|
182 |
+
'title' => __( 'Delete connection', 'posts-to-posts' )
|
183 |
+
), __( 'Delete connection', 'posts-to-posts' ) );
|
184 |
+
}
|
185 |
+
|
186 |
+
protected function clear_connections_link() {
|
187 |
+
return html( 'a', array(
|
188 |
+
'href' => '#',
|
189 |
+
'title' => __( 'Delete all connections', 'posts-to-posts' )
|
190 |
+
), __( 'Delete all connections', 'posts-to-posts' ) );
|
191 |
}
|
192 |
|
193 |
protected function get_connected_ids( $post_id ) {
|
209 |
return array_intersect( $connected_posts, $post_ids ); // to preserve p2p_id keys
|
210 |
}
|
211 |
|
212 |
+
function get_search_args( $args, $post_id ) {
|
213 |
+
$args = array_merge( $args, array(
|
|
|
214 |
'post_type' => $this->to,
|
215 |
'post_status' => 'any',
|
216 |
'posts_per_page' => 5,
|
|
|
|
|
217 |
'suppress_filters' => false,
|
218 |
'update_post_term_cache' => false,
|
219 |
'update_post_meta_cache' => false
|
220 |
+
) );
|
221 |
+
|
222 |
+
if ( $this->prevent_duplicates )
|
223 |
+
$args['post__not_in'] = p2p_get_connected( $post_id, $this->direction );
|
224 |
+
|
225 |
+
return $args;
|
226 |
+
}
|
227 |
+
|
228 |
+
function get_recent_args( $post_id ) {
|
229 |
+
$args = array(
|
230 |
+
'numberposts' => 10,
|
231 |
+
'orderby' => 'post_date',
|
232 |
+
'order' => 'DESC',
|
233 |
+
'post_type' => $this->to,
|
234 |
+
'post_status' => 'publish',
|
235 |
+
'suppress_filters' => false //true
|
236 |
);
|
237 |
+
|
238 |
+
if ( $this->prevent_duplicates )
|
239 |
+
$args['post__not_in'] = p2p_get_connected( $post_id, $this->direction );
|
240 |
+
|
241 |
+
return $args;
|
242 |
}
|
243 |
}
|
244 |
|
ui/images/add.png
ADDED
Binary file
|
ui/images/delete.png
ADDED
Binary file
|
ui/ui.css
ADDED
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* General */
|
2 |
+
|
3 |
+
.button.inactive, .button.inactive:hover {
|
4 |
+
border-color: #bbb;
|
5 |
+
color: #aaa;
|
6 |
+
background: #f6f6f6;
|
7 |
+
text-shadow: none;
|
8 |
+
cursor: default;
|
9 |
+
}
|
10 |
+
|
11 |
+
.p2p-footer {
|
12 |
+
background-color: #f1f1f1;
|
13 |
+
border-top: 1px solid #ddd;
|
14 |
+
clear: both;
|
15 |
+
padding: 7px;
|
16 |
+
margin: 0 -6px -8px;
|
17 |
+
}
|
18 |
+
|
19 |
+
.p2p-footer .p2p-recent {
|
20 |
+
float: right;
|
21 |
+
}
|
22 |
+
|
23 |
+
.p2p-placeholder {
|
24 |
+
color: #AAA;
|
25 |
+
}
|
26 |
+
|
27 |
+
.p2p-connections,
|
28 |
+
.p2p-search,
|
29 |
+
.p2p-results {
|
30 |
+
margin-bottom: 8px;
|
31 |
+
}
|
32 |
+
|
33 |
+
/* Connections */
|
34 |
+
|
35 |
+
.p2p-results,
|
36 |
+
.p2p-connections {
|
37 |
+
background-color: #F9F9F9;
|
38 |
+
border-color: #DFDFDF;
|
39 |
+
border-radius: 3px;
|
40 |
+
border-spacing: 0;
|
41 |
+
border-style: solid;
|
42 |
+
border-width: 1px;
|
43 |
+
}
|
44 |
+
|
45 |
+
.p2p-results {
|
46 |
+
display: none;
|
47 |
+
}
|
48 |
+
|
49 |
+
.p2p-results td,
|
50 |
+
.p2p-connections td {
|
51 |
+
border-top: 1px solid #DFDFDF;
|
52 |
+
}
|
53 |
+
|
54 |
+
.p2p-connections th,
|
55 |
+
.p2p-connections td,
|
56 |
+
.p2p-results td {
|
57 |
+
padding-left: 6px;
|
58 |
+
padding-right: 6px;
|
59 |
+
}
|
60 |
+
|
61 |
+
th.p2p-col-delete,
|
62 |
+
td.p2p-col-delete,
|
63 |
+
td.p2p-col-add {
|
64 |
+
padding: 0;
|
65 |
+
}
|
66 |
+
|
67 |
+
.p2p-col-delete a,
|
68 |
+
.p2p-col-add a,
|
69 |
+
.p2p-col-delete img,
|
70 |
+
.p2p-col-add img {
|
71 |
+
padding: 5px 6px;
|
72 |
+
}
|
73 |
+
|
74 |
+
th.p2p-col-delete a {
|
75 |
+
padding-bottom: 8px;
|
76 |
+
}
|
77 |
+
|
78 |
+
.p2p-results tr:first-child td {
|
79 |
+
border-top: 0;
|
80 |
+
}
|
81 |
+
|
82 |
+
.p2p-connections {
|
83 |
+
width: 100%;
|
84 |
+
}
|
85 |
+
|
86 |
+
.p2p-connections th {
|
87 |
+
background-color: #F1F1F1;
|
88 |
+
text-align: left;
|
89 |
+
}
|
90 |
+
|
91 |
+
.p2p-connections td input {
|
92 |
+
width: 100%;
|
93 |
+
}
|
94 |
+
|
95 |
+
.p2p-col-add,
|
96 |
+
.p2p-col-delete {
|
97 |
+
width: 16px;
|
98 |
+
}
|
99 |
+
|
100 |
+
.p2p-col-add a,
|
101 |
+
.p2p-col-delete a {
|
102 |
+
display: block;
|
103 |
+
height: 16px;
|
104 |
+
margin-top: 1px;
|
105 |
+
opacity: 0.5;
|
106 |
+
text-indent: -9999px;
|
107 |
+
width: 16px;
|
108 |
+
}
|
109 |
+
|
110 |
+
.p2p-col-add a:hover,
|
111 |
+
.p2p-col-delete a:hover {
|
112 |
+
background-color: #f5f5f5;
|
113 |
+
border-right: 1px solid #ddd;
|
114 |
+
opacity: 1;
|
115 |
+
width: 15px;
|
116 |
+
}
|
117 |
+
|
118 |
+
.p2p-col-add a {
|
119 |
+
background: url("images/add.png") no-repeat scroll 50% 50% transparent;
|
120 |
+
}
|
121 |
+
|
122 |
+
.p2p-col-delete a {
|
123 |
+
background: url("images/delete.png") no-repeat scroll 50% 50% transparent;
|
124 |
+
}
|
125 |
+
|
126 |
+
#poststuff .p2p-box .p2p-add-new p {
|
127 |
+
margin-left: 5px;
|
128 |
+
}
|
129 |
+
|
130 |
+
.p2p-search .waiting {
|
131 |
+
margin-left: -20px;
|
132 |
+
opacity: 0.8;
|
133 |
+
vertical-align: -0.3em;
|
134 |
+
}
|
135 |
+
|
136 |
+
.p2p-search input {
|
137 |
+
background-color: transparent;
|
138 |
+
width: 150px;
|
139 |
+
padding-right: 22px;
|
140 |
+
margin: 0;
|
141 |
+
}
|
142 |
+
|
143 |
+
.p2p-notice {
|
144 |
+
margin-left: 5px;
|
145 |
+
}
|
146 |
+
|
147 |
+
#side-sortables .p2p-notice {
|
148 |
+
display: block;
|
149 |
+
margin-top: 10px;
|
150 |
+
}
|
151 |
+
|
152 |
+
.p2p-footer .waiting {
|
153 |
+
float: right;
|
154 |
+
margin: 3px 6px 0;
|
155 |
+
}
|
156 |
+
|
157 |
+
.p2p-nav {
|
158 |
+
display: none;
|
159 |
+
}
|
160 |
+
|
161 |
+
.p2p-nav > * {
|
162 |
+
float: left;
|
163 |
+
line-height: 13px;
|
164 |
+
padding-top: 3px;
|
165 |
+
padding-bottom: 3px;
|
166 |
+
margin-right: 5px;
|
167 |
+
}
|
168 |
+
|
ui/ui.js
CHANGED
@@ -1,73 +1,254 @@
|
|
1 |
jQuery(document).ready(function($) {
|
2 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
var $self = $(this),
|
4 |
-
$
|
5 |
-
|
6 |
-
|
|
|
|
|
|
|
7 |
|
8 |
-
$
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
-
$
|
15 |
|
16 |
-
|
|
|
17 |
|
18 |
-
|
|
|
|
|
19 |
|
20 |
return false;
|
21 |
});
|
22 |
|
23 |
-
|
24 |
-
|
25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
});
|
27 |
|
28 |
-
|
|
|
|
|
29 |
|
30 |
-
|
|
|
31 |
|
32 |
-
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
}
|
|
|
35 |
|
36 |
-
|
37 |
-
$
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
|
47 |
-
|
48 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
}
|
50 |
-
old_value = $self.val();
|
51 |
|
52 |
-
$
|
53 |
-
|
54 |
-
var data = {
|
55 |
-
action: 'p2p_search',
|
56 |
-
q: $self.val(),
|
57 |
-
box_id: $metabox.attr('id').replace('p2p-box-', ''),
|
58 |
-
reversed: +$metabox.hasClass('reversed')
|
59 |
-
};
|
60 |
|
61 |
-
|
62 |
-
$spinner.hide();
|
63 |
|
64 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
});
|
72 |
});
|
|
|
73 |
|
1 |
jQuery(document).ready(function($) {
|
2 |
+
|
3 |
+
// Placeholder support for IE
|
4 |
+
if (!jQuery('<input placeholder="1" />')[0].placeholder) {
|
5 |
+
jQuery('.p2p-search input[placeholder]').each(function(){
|
6 |
+
var $this = $(this);
|
7 |
+
if (!$this.val()) {
|
8 |
+
$this.val($this.attr('placeholder'));
|
9 |
+
$this.addClass('p2p-placeholder');
|
10 |
+
}
|
11 |
+
}).focus(function(e){
|
12 |
+
var $this = $(this);
|
13 |
+
if ($this.hasClass('p2p-placeholder')) {
|
14 |
+
$this.val('');
|
15 |
+
$this.removeClass('p2p-placeholder');
|
16 |
+
}
|
17 |
+
}).blur(function(e){
|
18 |
+
var $this = $(this);
|
19 |
+
if (!$this.val()) {
|
20 |
+
$this.addClass('p2p-placeholder');
|
21 |
+
$this.val($this.attr('placeholder'));
|
22 |
+
}
|
23 |
+
});
|
24 |
+
}
|
25 |
+
|
26 |
+
$('.p2p-add-new').each(function() {
|
27 |
+
var $metabox = $(this).closest('.inside'),
|
28 |
+
$connections = $metabox.find('.p2p-connections'),
|
29 |
+
$results = $metabox.find('.p2p-results'),
|
30 |
+
$searchInput = $metabox.find('.p2p-search :text'),
|
31 |
+
$pagination = $metabox.find('.p2p-nav'),
|
32 |
+
$addNew = $metabox.find('.p2p-add-new'),
|
33 |
+
base_data = {
|
34 |
+
box_id: $addNew.attr('data-box_id'),
|
35 |
+
direction: $addNew.attr('data-direction')
|
36 |
+
};
|
37 |
+
|
38 |
+
// Save the wp-spinner
|
39 |
+
var $spinner = $('#publishing-action .ajax-loading')
|
40 |
+
.clone()
|
41 |
+
.removeAttr('id')
|
42 |
+
.removeClass('ajax-loading')
|
43 |
+
.addClass('waiting');
|
44 |
+
|
45 |
+
// Delete all connections
|
46 |
+
$metabox.delegate('th.p2p-col-delete a', 'click', function() {
|
47 |
+
if ( !confirm(P2PAdmin_I18n.deleteConfirmMessage) )
|
48 |
+
return false;
|
49 |
+
|
50 |
var $self = $(this),
|
51 |
+
$td = $self.closest('td'),
|
52 |
+
data = $.extend( base_data, {
|
53 |
+
action: 'p2p_connections',
|
54 |
+
subaction: 'clear_connections',
|
55 |
+
post_id: $('#post_ID').val()
|
56 |
+
} );
|
57 |
|
58 |
+
$td.html( $spinner.show() );
|
59 |
+
|
60 |
+
$.post(ajaxurl, data, function(response) {
|
61 |
+
$connections.hide()
|
62 |
+
.find('tbody').html('');
|
63 |
+
|
64 |
+
$td.html( $self );
|
65 |
+
});
|
66 |
+
|
67 |
+
return false;
|
68 |
+
});
|
69 |
+
|
70 |
+
// Delete connection
|
71 |
+
$metabox.delegate('td.p2p-col-delete a', 'click', function() {
|
72 |
+
var $self = $(this),
|
73 |
+
$td = $self.closest('td'),
|
74 |
+
data = $.extend( base_data, {
|
75 |
+
action: 'p2p_connections',
|
76 |
+
subaction: 'disconnect',
|
77 |
+
p2p_id: $self.attr('data-p2p_id')
|
78 |
+
} );
|
79 |
|
80 |
+
$td.html( $spinner.show() );
|
81 |
|
82 |
+
$.post(ajaxurl, data, function(response) {
|
83 |
+
$td.closest('tr').remove();
|
84 |
|
85 |
+
if ( !$connections.find('tbody tr').length )
|
86 |
+
$connections.hide();
|
87 |
+
});
|
88 |
|
89 |
return false;
|
90 |
});
|
91 |
|
92 |
+
// Create connection
|
93 |
+
$metabox.delegate('td.p2p-col-add a', 'click', function() {
|
94 |
+
var $self = $(this),
|
95 |
+
$td = $self.closest('td'),
|
96 |
+
data = $.extend( base_data, {
|
97 |
+
action: 'p2p_connections',
|
98 |
+
subaction: 'connect',
|
99 |
+
from: $('#post_ID').val(),
|
100 |
+
to: $self.attr('data-post_id')
|
101 |
+
} );
|
102 |
+
|
103 |
+
$td.html( $spinner.show() );
|
104 |
+
|
105 |
+
$.post(ajaxurl, data, function(response) {
|
106 |
+
$connections.show()
|
107 |
+
.find('tbody').append(response);
|
108 |
+
|
109 |
+
if ( $addNew.attr('data-prevent_duplicates') ) {
|
110 |
+
$td.closest('tr').remove();
|
111 |
+
|
112 |
+
if ( !$results.find('tbody tr').length )
|
113 |
+
$results.hide();
|
114 |
+
} else {
|
115 |
+
$td.html( $self );
|
116 |
+
}
|
117 |
+
});
|
118 |
+
|
119 |
+
return false;
|
120 |
});
|
121 |
|
122 |
+
// Pagination
|
123 |
+
var current_page = 1,
|
124 |
+
total_pages = 0;
|
125 |
|
126 |
+
function find_posts(new_page, action, callback) {
|
127 |
+
new_page = new_page ? ( new_page > total_pages ? current_page : new_page ) : current_page;
|
128 |
|
129 |
+
var data = $.extend( base_data, {
|
130 |
+
action: 'p2p_search',
|
131 |
+
s: $searchInput.val(),
|
132 |
+
paged: new_page,
|
133 |
+
post_id: $('#post_ID').val()
|
134 |
+
} );
|
135 |
+
|
136 |
+
// show spinner
|
137 |
+
if ( 'search' === action ) {
|
138 |
+
$spinner.insertAfter( $searchInput );
|
139 |
+
} else {
|
140 |
+
$spinner.insertAfter( $metabox.find('.p2p-recent') );
|
141 |
}
|
142 |
+
$spinner.show();
|
143 |
|
144 |
+
$.getJSON(ajaxurl, data, function(response) {
|
145 |
+
$spinner.remove();
|
146 |
+
|
147 |
+
current_page = new_page;
|
148 |
+
|
149 |
+
$metabox.find('.p2p-search').find('.p2p-notice').remove();
|
150 |
+
|
151 |
+
$pagination.hide();
|
152 |
+
|
153 |
+
if ( 'undefined' === typeof response.rows ) {
|
154 |
+
$metabox.find('.p2p-search').append('<p class="p2p-notice">' + response.msg + '</p>');
|
155 |
+
$results.hide()
|
156 |
+
.find('tbody').html('');
|
157 |
+
} else {
|
158 |
+
$results.show()
|
159 |
+
.find('tbody').html(response.rows);
|
160 |
+
|
161 |
+
total_pages = response.pages;
|
162 |
+
|
163 |
+
// update pagination
|
164 |
+
if ( total_pages > 1 ) {
|
165 |
+
$pagination.show();
|
166 |
+
}
|
167 |
+
|
168 |
+
if ( 1 === current_page ) {
|
169 |
+
$metabox.find('.p2p-prev').addClass('inactive');
|
170 |
+
} else {
|
171 |
+
$metabox.find('.p2p-prev').removeClass('inactive');
|
172 |
+
}
|
173 |
+
|
174 |
+
if ( total_pages === current_page ) {
|
175 |
+
$metabox.find('.p2p-next').addClass('inactive');
|
176 |
+
} else {
|
177 |
+
$metabox.find('.p2p-next').removeClass('inactive');
|
178 |
+
}
|
179 |
+
|
180 |
+
$metabox.find('.p2p-current').html(current_page);
|
181 |
+
$metabox.find('.p2p-total').html(total_pages);
|
182 |
+
|
183 |
+
if ( undefined !== callback )
|
184 |
+
callback();
|
185 |
}
|
186 |
+
});
|
187 |
+
}
|
188 |
+
|
189 |
+
// Delegate recent
|
190 |
+
$metabox.delegate('.p2p-recent', 'click', function() {
|
191 |
+
var $button = $(this);
|
192 |
+
|
193 |
+
if ( $button.hasClass('inactive') )
|
194 |
+
return false;
|
195 |
+
|
196 |
+
$metabox.find('.p2p-search :text')
|
197 |
+
.val('')
|
198 |
+
.blur(); // so that placeholder is shown again in IE
|
199 |
+
|
200 |
+
$button.addClass('inactive');
|
201 |
+
find_posts(1, 'recent', function() {
|
202 |
+
$button.removeClass('inactive');
|
203 |
+
});
|
204 |
+
|
205 |
+
return false;
|
206 |
+
});
|
207 |
|
208 |
+
// Search posts
|
209 |
+
var delayed, old_value = '';
|
210 |
+
|
211 |
+
$metabox.find('.p2p-search :text')
|
212 |
+
.keypress(function (ev) {
|
213 |
+
if ( 13 === ev.keyCode )
|
214 |
+
return false;
|
215 |
+
})
|
216 |
+
|
217 |
+
.keyup(function (ev) {
|
218 |
+
if ( undefined !== delayed ) {
|
219 |
+
clearTimeout(delayed);
|
220 |
}
|
|
|
221 |
|
222 |
+
var $self = $(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
|
224 |
+
delayed = setTimeout(function() {
|
|
|
225 |
|
226 |
+
if ( $self.val() === old_value ) {
|
227 |
+
return;
|
228 |
+
}
|
229 |
+
old_value = $self.val();
|
230 |
+
|
231 |
+
find_posts(1, 'search');
|
232 |
+
}, 400);
|
233 |
+
});
|
234 |
+
|
235 |
+
// Pagination
|
236 |
+
$metabox.delegate('.p2p-prev, .p2p-next', 'click', function() {
|
237 |
+
var $self = $(this),
|
238 |
+
new_page = current_page;
|
239 |
|
240 |
+
if ( $self.hasClass('inactive') )
|
241 |
+
return false;
|
242 |
+
|
243 |
+
if ( $self.hasClass('p2p-prev') )
|
244 |
+
new_page--;
|
245 |
+
else
|
246 |
+
new_page++;
|
247 |
+
|
248 |
+
find_posts(new_page, 'paginate');
|
249 |
+
|
250 |
+
return false;
|
251 |
});
|
252 |
});
|
253 |
+
});
|
254 |
|
ui/ui.php
CHANGED
@@ -1,19 +1,17 @@
|
|
1 |
<?php
|
2 |
|
3 |
abstract class P2P_Box {
|
|
|
|
|
4 |
|
5 |
protected $reversed;
|
6 |
protected $direction;
|
7 |
|
8 |
protected $box_id;
|
9 |
-
private $input;
|
10 |
|
11 |
-
abstract function save( $post_id, $data );
|
12 |
abstract function box( $post_id );
|
13 |
|
14 |
-
|
15 |
-
return $this->input->get_name( $name );
|
16 |
-
}
|
17 |
|
18 |
|
19 |
// Internal stuff
|
@@ -25,162 +23,180 @@ abstract class P2P_Box {
|
|
25 |
|
26 |
$this->box_id = $box_id;
|
27 |
|
28 |
-
$this->input = new p2pInput( array( 'p2p', $box_id ) );
|
29 |
-
|
30 |
$this->direction = $direction;
|
31 |
|
32 |
$this->reversed = ( 'to' == $direction );
|
33 |
|
34 |
if ( $this->reversed )
|
35 |
list( $this->to, $this->from ) = array( $this->from, $this->to );
|
|
|
|
|
36 |
}
|
37 |
|
38 |
function _register( $from ) {
|
39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
|
41 |
-
if ( empty( $title ) )
|
42 |
-
$title = get_post_type_object( $this->to )->labels->name;
|
|
|
43 |
|
44 |
add_meta_box(
|
45 |
'p2p-connections-' . $this->box_id,
|
46 |
$title,
|
47 |
array( $this, '_box' ),
|
48 |
$from,
|
49 |
-
|
50 |
'default'
|
51 |
);
|
52 |
}
|
53 |
|
54 |
-
function _save( $post_id ) {
|
55 |
-
$data = $this->input->extract( $_POST );
|
56 |
-
|
57 |
-
if ( is_null( $data ) )
|
58 |
-
return;
|
59 |
-
|
60 |
-
$this->save( $post_id, $data );
|
61 |
-
}
|
62 |
-
|
63 |
function _box( $post ) {
|
64 |
$this->box( $post->ID );
|
65 |
}
|
66 |
}
|
67 |
|
68 |
|
69 |
-
class p2pInput {
|
70 |
-
|
71 |
-
private $prefix;
|
72 |
-
|
73 |
-
function __construct( $prefix = array() ) {
|
74 |
-
$this->prefix = $prefix;
|
75 |
-
}
|
76 |
-
|
77 |
-
function get_name( $suffix ) {
|
78 |
-
$name_a = array_merge( $this->prefix, (array) $suffix );
|
79 |
-
|
80 |
-
$name = array_shift( $name_a );
|
81 |
-
foreach ( $name_a as $key )
|
82 |
-
$name .= '[' . esc_attr( $key ) . ']';
|
83 |
-
|
84 |
-
return $name;
|
85 |
-
}
|
86 |
-
|
87 |
-
function extract( $value, $suffix = array() ) {
|
88 |
-
$name_a = array_merge( $this->prefix, (array) $suffix );
|
89 |
-
|
90 |
-
foreach ( $name_a as $key ) {
|
91 |
-
if ( !isset( $value[ $key ] ) )
|
92 |
-
return null;
|
93 |
-
|
94 |
-
$value = $value[$key];
|
95 |
-
}
|
96 |
-
|
97 |
-
return $value;
|
98 |
-
}
|
99 |
-
}
|
100 |
-
|
101 |
-
|
102 |
class P2P_Connection_Types {
|
103 |
|
104 |
private static $ctypes = array();
|
105 |
|
106 |
static public function register( $args ) {
|
107 |
-
$args = wp_parse_args( $args, array(
|
108 |
-
'from' => '',
|
109 |
-
'to' => '',
|
110 |
-
'box' => 'P2P_Box_Multiple',
|
111 |
-
'title' => '',
|
112 |
-
'reciprocal' => false
|
113 |
-
) );
|
114 |
-
|
115 |
self::$ctypes[] = $args;
|
116 |
}
|
117 |
|
118 |
static function init() {
|
119 |
add_action( 'add_meta_boxes', array( __CLASS__, '_register' ) );
|
120 |
-
|
|
|
121 |
add_action( 'wp_ajax_p2p_search', array( __CLASS__, 'ajax_search' ) );
|
|
|
122 |
}
|
123 |
|
124 |
static function _register( $from ) {
|
125 |
-
|
|
|
|
|
|
|
|
|
|
|
126 |
$ctype->_register( $from );
|
127 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
}
|
129 |
|
130 |
-
|
131 |
-
$
|
132 |
-
if ( defined( 'DOING_AJAX' ) || defined( 'DOING_CRON' ) || empty( $_POST ) || 'revision' == $from )
|
133 |
return;
|
134 |
|
135 |
-
foreach (
|
136 |
-
|
|
|
|
|
137 |
}
|
138 |
}
|
139 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
function ajax_search() {
|
141 |
-
add_filter( 'posts_search', array( __CLASS__, '_search_by_title' ) );
|
142 |
|
143 |
-
$
|
144 |
-
$reversed = (bool) $_GET['reversed'];
|
145 |
|
146 |
-
|
147 |
-
|
|
|
|
|
148 |
|
149 |
-
$
|
150 |
-
$box = new $args['box']($args, $reversed, $box_id);
|
151 |
|
152 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
153 |
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
}
|
159 |
|
160 |
-
|
|
|
|
|
161 |
}
|
162 |
|
163 |
-
function _search_by_title( $sql ) {
|
164 |
remove_filter( current_filter(), array( __CLASS__, __FUNCTION__ ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
|
166 |
-
|
|
|
|
|
167 |
|
168 |
-
|
|
|
|
|
|
|
|
|
|
|
169 |
}
|
170 |
|
171 |
private static function filter_ctypes( $post_type ) {
|
172 |
$r = array();
|
|
|
173 |
foreach ( self::$ctypes as $box_id => $args ) {
|
174 |
$direction = false;
|
175 |
|
176 |
-
if ( $args['reciprocal'] && $args['from'] == $args['to'] ) {
|
177 |
-
$direction = 'any';
|
178 |
} elseif ( $args['reciprocal'] && $post_type == $args['to'] ) {
|
179 |
$direction = 'to';
|
180 |
} elseif ( $post_type == $args['from'] ) {
|
181 |
$direction = 'from';
|
182 |
} else {
|
183 |
-
continue;
|
184 |
}
|
185 |
|
186 |
if ( !$direction )
|
1 |
<?php
|
2 |
|
3 |
abstract class P2P_Box {
|
4 |
+
public $from;
|
5 |
+
public $to;
|
6 |
|
7 |
protected $reversed;
|
8 |
protected $direction;
|
9 |
|
10 |
protected $box_id;
|
|
|
11 |
|
|
|
12 |
abstract function box( $post_id );
|
13 |
|
14 |
+
function setup() {}
|
|
|
|
|
15 |
|
16 |
|
17 |
// Internal stuff
|
23 |
|
24 |
$this->box_id = $box_id;
|
25 |
|
|
|
|
|
26 |
$this->direction = $direction;
|
27 |
|
28 |
$this->reversed = ( 'to' == $direction );
|
29 |
|
30 |
if ( $this->reversed )
|
31 |
list( $this->to, $this->from ) = array( $this->from, $this->to );
|
32 |
+
|
33 |
+
$this->setup();
|
34 |
}
|
35 |
|
36 |
function _register( $from ) {
|
37 |
+
if ( is_array( $this->title ) ) {
|
38 |
+
$key = $this->reversed ? 'to' : 'from';
|
39 |
+
|
40 |
+
if ( isset( $this->title[ $key ] ) )
|
41 |
+
$title = $this->title[ $key ];
|
42 |
+
else
|
43 |
+
$title = '';
|
44 |
+
} else {
|
45 |
+
$title = $this->title;
|
46 |
+
}
|
47 |
|
48 |
+
if ( empty( $title ) ) {
|
49 |
+
$title = sprintf( __( 'Connected %s', 'posts-to-posts' ), get_post_type_object( $this->to )->labels->name );
|
50 |
+
}
|
51 |
|
52 |
add_meta_box(
|
53 |
'p2p-connections-' . $this->box_id,
|
54 |
$title,
|
55 |
array( $this, '_box' ),
|
56 |
$from,
|
57 |
+
$this->context,
|
58 |
'default'
|
59 |
);
|
60 |
}
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
function _box( $post ) {
|
63 |
$this->box( $post->ID );
|
64 |
}
|
65 |
}
|
66 |
|
67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
class P2P_Connection_Types {
|
69 |
|
70 |
private static $ctypes = array();
|
71 |
|
72 |
static public function register( $args ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
self::$ctypes[] = $args;
|
74 |
}
|
75 |
|
76 |
static function init() {
|
77 |
add_action( 'add_meta_boxes', array( __CLASS__, '_register' ) );
|
78 |
+
|
79 |
+
add_action( 'save_post', array( __CLASS__, 'save' ), 10, 2 );
|
80 |
add_action( 'wp_ajax_p2p_search', array( __CLASS__, 'ajax_search' ) );
|
81 |
+
add_action( 'wp_ajax_p2p_connections', array( __CLASS__, 'ajax_connections' ) );
|
82 |
}
|
83 |
|
84 |
static function _register( $from ) {
|
85 |
+
$filtered = self::filter_ctypes( $from );
|
86 |
+
|
87 |
+
if ( empty( $filtered ) )
|
88 |
+
return;
|
89 |
+
|
90 |
+
foreach ( $filtered as $ctype ) {
|
91 |
$ctype->_register( $from );
|
92 |
}
|
93 |
+
|
94 |
+
wp_enqueue_style( 'p2p-admin', plugins_url( 'ui.css', __FILE__ ), array(), '0.7-beta' );
|
95 |
+
wp_enqueue_script( 'p2p-admin', plugins_url( 'ui.js', __FILE__ ), array( 'jquery' ), '0.7-beta', true );
|
96 |
+
wp_localize_script( 'p2p-admin', 'P2PAdmin_I18n', array(
|
97 |
+
'deleteConfirmMessage' => __( 'Are you sure you want to delete all connections?', 'posts-to-posts' ),
|
98 |
+
) );
|
99 |
}
|
100 |
|
101 |
+
function save( $post_id, $post ) {
|
102 |
+
if ( 'revision' == $post->post_type || !isset( $_POST['p2p_meta'] ) )
|
|
|
103 |
return;
|
104 |
|
105 |
+
foreach ( $_POST['p2p_meta'] as $p2p_id => $data ) {
|
106 |
+
foreach ( $data as $key => $value ) {
|
107 |
+
p2p_update_meta( $p2p_id, $key, $value );
|
108 |
+
}
|
109 |
}
|
110 |
}
|
111 |
|
112 |
+
function ajax_connections() {
|
113 |
+
$box = self::ajax_make_box();
|
114 |
+
|
115 |
+
$ptype_obj = get_post_type_object( $box->from );
|
116 |
+
if ( !current_user_can( $ptype_obj->cap->edit_posts ) )
|
117 |
+
die(-1);
|
118 |
+
|
119 |
+
$subaction = $_POST['subaction'];
|
120 |
+
|
121 |
+
$box->$subaction();
|
122 |
+
}
|
123 |
+
|
124 |
+
function ajax_disconnect() {
|
125 |
+
$box = self::ajax_make_box();
|
126 |
+
|
127 |
+
$box->disconnect();
|
128 |
+
}
|
129 |
+
|
130 |
function ajax_search() {
|
131 |
+
add_filter( 'posts_search', array( __CLASS__, '_search_by_title' ), 10, 2 );
|
132 |
|
133 |
+
$box = self::ajax_make_box();
|
|
|
134 |
|
135 |
+
$args = array(
|
136 |
+
's' => $_GET['s'],
|
137 |
+
'paged' => $_GET['paged']
|
138 |
+
);
|
139 |
|
140 |
+
$query = new WP_Query( $box->get_search_args( $args, $_GET['post_id'] ) );
|
|
|
141 |
|
142 |
+
if ( !$query->have_posts() ) {
|
143 |
+
$results = array(
|
144 |
+
'msg' => get_post_type_object( $box->to )->labels->not_found,
|
145 |
+
);
|
146 |
+
} else {
|
147 |
+
ob_start();
|
148 |
+
foreach ( $query->posts as $post ) {
|
149 |
+
$box->results_row( $post );
|
150 |
+
}
|
151 |
|
152 |
+
$results = array(
|
153 |
+
'rows' => ob_get_clean(),
|
154 |
+
'pages' => $query->max_num_pages
|
155 |
+
);
|
156 |
}
|
157 |
|
158 |
+
echo json_encode( $results );
|
159 |
+
|
160 |
+
die;
|
161 |
}
|
162 |
|
163 |
+
function _search_by_title( $sql, $wp_query ) {
|
164 |
remove_filter( current_filter(), array( __CLASS__, __FUNCTION__ ) );
|
165 |
+
|
166 |
+
if ( $wp_query->is_search ) {
|
167 |
+
list( $sql ) = explode( ' OR ', $sql, 2 );
|
168 |
+
return $sql . '))';
|
169 |
+
}
|
170 |
+
|
171 |
+
return $sql;
|
172 |
+
}
|
173 |
|
174 |
+
private static function ajax_make_box() {
|
175 |
+
$box_id = absint( $_REQUEST['box_id'] );
|
176 |
+
$direction = $_REQUEST['direction'];
|
177 |
|
178 |
+
if ( !isset( self::$ctypes[ $box_id ] ) )
|
179 |
+
die(0);
|
180 |
+
|
181 |
+
$args = self::$ctypes[ $box_id ];
|
182 |
+
|
183 |
+
return new $args['box']($args, $direction, $box_id);
|
184 |
}
|
185 |
|
186 |
private static function filter_ctypes( $post_type ) {
|
187 |
$r = array();
|
188 |
+
|
189 |
foreach ( self::$ctypes as $box_id => $args ) {
|
190 |
$direction = false;
|
191 |
|
192 |
+
if ( $args['reciprocal'] && $post_type == $args['from'] && $args['from'] == $args['to'] ) {
|
193 |
+
$direction = 'any';
|
194 |
} elseif ( $args['reciprocal'] && $post_type == $args['to'] ) {
|
195 |
$direction = 'to';
|
196 |
} elseif ( $post_type == $args['from'] ) {
|
197 |
$direction = 'from';
|
198 |
} else {
|
199 |
+
continue;
|
200 |
}
|
201 |
|
202 |
if ( !$direction )
|