Version Description
- introduced 'connected_from', 'connected_to', 'connected' vars to WP_Query
- replaced $reciprocal with $data as the third argument
- p2p_register_connection_type() accepts an associative array as arguments
- removed p2p_list_connected()
- added p2p_delete_connection()
- more info
Download this release
Release Info
Developer | scribu |
Plugin | Posts 2 Posts |
Version | 0.4 |
Comparing to | |
See all releases |
Code changes from version 0.3 to 0.4
- admin/admin.php +0 -198
- api.php +87 -110
- core.php +0 -77
- lang/posts-to-posts.pot +3 -3
- posts-to-posts.php +42 -9
- readme.txt +12 -5
- scb/AdminPage.php +14 -15
- scb/BoxesPage.php +37 -14
- scb/QueryManipulation.php +1 -1
- scb/Rewrite.php +0 -24
- scb/Util.php +2 -17
- scb/load.php +2 -2
- storage.php +183 -0
- {admin → ui}/admin.js +1 -1
- ui/boxes.php +171 -0
- ui/ui.js +60 -0
- ui/ui.php +157 -0
admin/admin.php
DELETED
@@ -1,198 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class P2P_Admin {
|
4 |
-
|
5 |
-
private static $connections;
|
6 |
-
|
7 |
-
function init( $file ) {
|
8 |
-
add_action( 'admin_print_styles-post.php', array( __CLASS__, 'scripts' ) );
|
9 |
-
add_action( 'admin_print_styles-post-new.php', array( __CLASS__, 'scripts' ) );
|
10 |
-
|
11 |
-
add_action( 'add_meta_boxes', array( __CLASS__, 'register' ) );
|
12 |
-
|
13 |
-
add_action( 'save_post', array( __CLASS__, 'save' ), 10 );
|
14 |
-
add_action( 'wp_ajax_p2p_search', array( __CLASS__, 'ajax_search' ) );
|
15 |
-
|
16 |
-
add_action( 'admin_notices', array( __CLASS__, 'migrate' ) );
|
17 |
-
}
|
18 |
-
|
19 |
-
function migrate() {
|
20 |
-
if ( !isset( $_GET['migrate_p2p'] ) || !current_user_can( 'administrator' ) )
|
21 |
-
return;
|
22 |
-
|
23 |
-
global $wpdb;
|
24 |
-
|
25 |
-
$rows = $wpdb->get_results( "
|
26 |
-
SELECT post_id as post_a, meta_value as post_b
|
27 |
-
FROM $wpdb->postmeta
|
28 |
-
WHERE meta_key = '_p2p'
|
29 |
-
" );
|
30 |
-
|
31 |
-
$grouped = array();
|
32 |
-
foreach ( $rows as $row )
|
33 |
-
$grouped[ $row->post_a ][] = $row->post_b;
|
34 |
-
|
35 |
-
foreach ( $grouped as $post_a => $post_b )
|
36 |
-
p2p_connect( $post_a, $post_b );
|
37 |
-
|
38 |
-
$wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_p2p'" );
|
39 |
-
|
40 |
-
printf( "<div class='updated'><p>Migrated %s connections.</p></div>", count( $rows ) );
|
41 |
-
}
|
42 |
-
|
43 |
-
function scripts() {
|
44 |
-
wp_enqueue_script( 'p2p-admin-js', plugins_url( 'admin.js', __FILE__ ), array( 'jquery' ), '0.2', true );
|
45 |
-
|
46 |
-
?>
|
47 |
-
<style type="text/css">
|
48 |
-
.p2p_connected {margin: 10px 4px}
|
49 |
-
.p2p_results {margin: -5px 6px 10px}
|
50 |
-
.p2p_metabox .waiting {vertical-align: -.4em}
|
51 |
-
</style>
|
52 |
-
<?php
|
53 |
-
}
|
54 |
-
|
55 |
-
function save( $post_a ) {
|
56 |
-
$current_ptype = get_post_type( $post_a );
|
57 |
-
if ( defined( 'DOING_AJAX' ) || defined( 'DOING_CRON' ) || empty( $_POST ) || 'revision' == $current_ptype )
|
58 |
-
return;
|
59 |
-
|
60 |
-
self::cache_connections( $post_a );
|
61 |
-
|
62 |
-
foreach ( p2p_get_connection_types( $current_ptype ) as $post_type ) {
|
63 |
-
if ( !isset( $_POST['p2p_connected_ids_' . $post_type] ) )
|
64 |
-
continue;
|
65 |
-
|
66 |
-
$reciprocal = p2p_connection_type_is_reciprocal( $current_ptype, $post_type );
|
67 |
-
|
68 |
-
$old_connections = (array) @self::$connections[ $post_type ];
|
69 |
-
$new_connections = explode( ',', $_POST[ 'p2p_connected_ids_' . $post_type ] );
|
70 |
-
|
71 |
-
p2p_disconnect( $post_a, array_diff( $old_connections, $new_connections ), $reciprocal );
|
72 |
-
p2p_connect( $post_a, array_diff( $new_connections, $old_connections ), $reciprocal );
|
73 |
-
}
|
74 |
-
}
|
75 |
-
|
76 |
-
private function cache_connections( $post_id ) {
|
77 |
-
$posts = p2p_get_connected( $post_id, 'from', 'any', 'objects' );
|
78 |
-
|
79 |
-
$connections = array();
|
80 |
-
foreach ( $posts as $post )
|
81 |
-
$connections[ $post->post_type ][] = $post->ID;
|
82 |
-
|
83 |
-
self::$connections = $connections;
|
84 |
-
}
|
85 |
-
|
86 |
-
function register( $post_type ) {
|
87 |
-
global $post;
|
88 |
-
|
89 |
-
self::cache_connections( $post->ID );
|
90 |
-
|
91 |
-
foreach ( p2p_get_connection_types( $post_type ) as $type ) {
|
92 |
-
add_meta_box(
|
93 |
-
'p2p-connections-' . $type,
|
94 |
-
__( 'Connected', 'posts-to-posts' ) . ' ' . get_post_type_object( $type )->labels->name,
|
95 |
-
array( __CLASS__, 'box' ),
|
96 |
-
$post_type,
|
97 |
-
'side',
|
98 |
-
'default',
|
99 |
-
$type
|
100 |
-
);
|
101 |
-
}
|
102 |
-
}
|
103 |
-
|
104 |
-
function box( $post, $args ) {
|
105 |
-
$post_type = $args['args'];
|
106 |
-
|
107 |
-
$connected_ids = @self::$connections[ $post_type ];
|
108 |
-
|
109 |
-
?>
|
110 |
-
|
111 |
-
<div class="p2p_metabox">
|
112 |
-
<div class="hide-if-no-js checkboxes">
|
113 |
-
<ul class="p2p_connected">
|
114 |
-
<?php if ( empty( $connected_ids ) ) { ?>
|
115 |
-
<li class="howto"><?php _e( 'No connections.', 'posts-to-posts' ); ?></li>
|
116 |
-
<?php } else { ?>
|
117 |
-
<?php foreach ( $connected_ids as $id ) {
|
118 |
-
echo html( 'li', scbForms::input( array(
|
119 |
-
'type' => 'checkbox',
|
120 |
-
'name' => "p2p_checkbox_$id",
|
121 |
-
'value' => $id,
|
122 |
-
'checked' => true,
|
123 |
-
'desc' => get_the_title( $id ),
|
124 |
-
'extra' => array( 'autocomplete' => 'off' ),
|
125 |
-
) ) );
|
126 |
-
} ?>
|
127 |
-
<?php } ?>
|
128 |
-
</ul>
|
129 |
-
|
130 |
-
<?php echo html( 'p class="p2p_search"',
|
131 |
-
scbForms::input( array(
|
132 |
-
'type' => 'text',
|
133 |
-
'name' => 'p2p_search_' . $post_type,
|
134 |
-
'desc' => __( 'Search', 'posts-to-posts' ) . ':',
|
135 |
-
'desc_pos' => 'before',
|
136 |
-
'extra' => array( 'autocomplete' => 'off' ),
|
137 |
-
) )
|
138 |
-
. '<img alt="" src="' . admin_url( 'images/wpspin_light.gif' ) . '" class="waiting" style="display: none;">'
|
139 |
-
); ?>
|
140 |
-
|
141 |
-
<ul class="p2p_results"></ul>
|
142 |
-
<p class="howto"><?php _e( 'Start typing name of connected post type and click on it if you want to connect it.', 'posts-to-posts' ); ?></p>
|
143 |
-
</div>
|
144 |
-
|
145 |
-
<div class="hide-if-js">
|
146 |
-
<?php echo scbForms::input( array(
|
147 |
-
'type' => 'text',
|
148 |
-
'name' => 'p2p_connected_ids_' . $post_type,
|
149 |
-
'value' => implode( ',', $connected_ids ),
|
150 |
-
'extra' => array( 'class' => 'p2p_connected_ids' ),
|
151 |
-
) ); ?>
|
152 |
-
<p class="howto"><?php _e( 'Enter IDs of connected post types separated by commas, or turn on JavaScript!', 'posts-to-posts' ); ?></p>
|
153 |
-
</div>
|
154 |
-
</div>
|
155 |
-
<?php
|
156 |
-
}
|
157 |
-
|
158 |
-
function ajax_search() {
|
159 |
-
$post_type_name = $_GET['post_type'];
|
160 |
-
|
161 |
-
if ( !post_type_exists( $post_type_name ) )
|
162 |
-
die;
|
163 |
-
|
164 |
-
$args = array(
|
165 |
-
's' => $_GET['q'],
|
166 |
-
'post_type' => $post_type_name,
|
167 |
-
'post_status' => 'any',
|
168 |
-
'posts_per_page' => 5,
|
169 |
-
'order' => 'ASC',
|
170 |
-
'orderby' => 'title',
|
171 |
-
'suppress_filters' => true,
|
172 |
-
'update_post_term_cache' => false,
|
173 |
-
'update_post_meta_cache' => false
|
174 |
-
);
|
175 |
-
|
176 |
-
$posts = new WP_Query( $args );
|
177 |
-
|
178 |
-
$results = array();
|
179 |
-
while ( $posts->have_posts() ) {
|
180 |
-
$posts->the_post();
|
181 |
-
$results[ get_the_ID() ] = get_the_title();
|
182 |
-
}
|
183 |
-
|
184 |
-
die( json_encode( $results ) );
|
185 |
-
}
|
186 |
-
|
187 |
-
private function get_post_list( $post_type ) {
|
188 |
-
$args = array(
|
189 |
-
'post_type' => $post_type,
|
190 |
-
'post_status' => 'any',
|
191 |
-
'nopaging' => true,
|
192 |
-
'cache_results' => false,
|
193 |
-
);
|
194 |
-
|
195 |
-
return scbUtil::objects_to_assoc( get_posts( $args ), 'ID', 'post_title' );
|
196 |
-
}
|
197 |
-
}
|
198 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
api.php
CHANGED
@@ -4,153 +4,130 @@
|
|
4 |
* Register a connection between two post types.
|
5 |
* This creates the appropriate meta box in the admin edit screen
|
6 |
*
|
7 |
-
* @param
|
8 |
-
*
|
9 |
-
*
|
|
|
|
|
|
|
10 |
*/
|
11 |
-
function p2p_register_connection_type( $
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
foreach ( $post_type_b as $ptype_b )
|
27 |
-
p2p_register_connection_type( $ptype_b, $post_type_a, false );
|
28 |
}
|
29 |
|
30 |
/**
|
31 |
-
*
|
32 |
-
*
|
33 |
-
* @param string $post_type_a The first end of the connection
|
34 |
*
|
35 |
-
* @
|
|
|
|
|
36 |
*/
|
37 |
-
function
|
38 |
-
|
|
|
|
|
|
|
|
|
39 |
}
|
40 |
|
41 |
/**
|
42 |
-
*
|
43 |
-
*
|
44 |
-
* @param string $post_type_a The first end of the connection
|
45 |
-
* @param string $post_type_b The second end of the connection
|
46 |
*
|
47 |
-
* @
|
|
|
|
|
48 |
*/
|
49 |
-
function
|
50 |
-
|
51 |
-
|
52 |
-
|
|
|
|
|
53 |
}
|
54 |
|
55 |
/**
|
56 |
-
*
|
57 |
*
|
58 |
-
* @param int $
|
59 |
-
* @param
|
60 |
-
* @param
|
61 |
-
*/
|
62 |
-
function p2p_connect( $post_a, $post_b, $reciprocal = false ) {
|
63 |
-
Posts2Posts::connect( $post_a, $post_b );
|
64 |
-
|
65 |
-
if ( $reciprocal )
|
66 |
-
foreach ( $post_b as $single )
|
67 |
-
Posts2Posts::connect( $single, $post_a );
|
68 |
-
}
|
69 |
-
|
70 |
-
/**
|
71 |
-
* Disconnect a post from another one
|
72 |
*
|
73 |
-
* @
|
74 |
-
* @param int|array $post_b The second end of the connection
|
75 |
-
* @param bool $reciprocal Wether the connection is reciprocal or not
|
76 |
*/
|
77 |
-
function
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
|
|
|
|
|
|
|
|
83 |
}
|
84 |
|
85 |
/**
|
86 |
* See if a certain post is connected to another one
|
87 |
*
|
88 |
-
* @param int $
|
89 |
-
* @param int $
|
|
|
90 |
*
|
91 |
* @return bool True if the connection exists, false otherwise
|
92 |
*/
|
93 |
-
function p2p_is_connected( $
|
94 |
-
$
|
95 |
-
|
96 |
-
if ( $reciprocal )
|
97 |
-
$r = $r && Posts2Posts::is_connected( $post_b, $post_a );
|
98 |
|
99 |
-
return $
|
100 |
}
|
101 |
|
102 |
/**
|
103 |
-
*
|
104 |
*
|
105 |
-
* @param int $
|
106 |
-
* @param string $direction The direction of the connection. Can be 'to' or 'from'
|
107 |
-
* @param string|array $post_type The post type of the connected posts.
|
108 |
-
* @param string $output Can be 'ids' or 'objects'
|
109 |
*
|
110 |
-
* @return
|
111 |
-
* @return object A WP_Query instance otherwise
|
112 |
*/
|
113 |
-
function
|
114 |
-
|
115 |
-
|
116 |
-
if ( empty( $ids ) )
|
117 |
-
return array();
|
118 |
-
|
119 |
-
if ( 'any' == $post_type && 'ids' == $output )
|
120 |
-
return $ids;
|
121 |
-
|
122 |
-
$args = array(
|
123 |
-
'post__in' => $ids,
|
124 |
-
'post_type'=> $post_type,
|
125 |
-
'post_status' => 'any',
|
126 |
-
'nopaging' => true,
|
127 |
-
);
|
128 |
-
|
129 |
-
$posts = get_posts( $args );
|
130 |
|
131 |
-
|
132 |
-
|
133 |
|
134 |
-
|
135 |
-
|
|
|
136 |
|
137 |
-
|
138 |
-
|
139 |
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
function p2p_list_connected( $post_id, $direction = 'to', $post_type = 'any' ) {
|
146 |
-
$posts = p2p_get_connected( $post_id, $direction, $post_type, 'objects' );
|
147 |
|
148 |
-
|
149 |
-
|
|
|
|
|
|
|
150 |
|
151 |
-
|
152 |
-
|
153 |
-
echo html( 'li', html_link( get_permalink( $post->ID ), get_the_title( $post->ID ) ) );
|
154 |
-
echo '</ul>';
|
155 |
}
|
156 |
|
4 |
* Register a connection between two post types.
|
5 |
* This creates the appropriate meta box in the admin edit screen
|
6 |
*
|
7 |
+
* @param array $args Can be:
|
8 |
+
* - 'from' string|array The first end of the connection
|
9 |
+
* - 'to' string|array The second end of the connection
|
10 |
+
* - 'title' string The box's title
|
11 |
+
* - 'reciprocal' bool wether to show the box on both sides of the connection
|
12 |
+
* - 'box' string A class that handles displaying and saving connections. Default: P2P_Box_Multiple
|
13 |
*/
|
14 |
+
function p2p_register_connection_type( $args ) {
|
15 |
+
$argv = func_get_args();
|
16 |
+
|
17 |
+
if ( count( $argv ) > 1 ) {
|
18 |
+
$args = array();
|
19 |
+
list( $args['from'], $args['to'], $args['reciprocal'] ) = $argv;
|
20 |
+
}
|
21 |
+
|
22 |
+
foreach ( (array) $args['from'] as $from ) {
|
23 |
+
foreach ( (array) $args['to'] as $to ) {
|
24 |
+
$args['from'] = $from;
|
25 |
+
$args['to'] = $to;
|
26 |
+
P2P_Connection_Types::register( $args );
|
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
|
36 |
+
* @param array $data additional data about the connection
|
37 |
*/
|
38 |
+
function p2p_connect( $from, $to, $data = array() ) {
|
39 |
+
foreach ( (array) $from as $from ) {
|
40 |
+
foreach ( (array) $to as $to ) {
|
41 |
+
P2P_Connections::connect( $from, $to, $data );
|
42 |
+
}
|
43 |
+
}
|
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
|
51 |
+
* @param array $data additional data about the connection to filter against
|
52 |
*/
|
53 |
+
function p2p_disconnect( $from, $to, $data = array() ) {
|
54 |
+
foreach ( (array) $from as $from ) {
|
55 |
+
foreach ( (array) $to as $to ) {
|
56 |
+
P2P_Connections::disconnect( $from, $to, $data );
|
57 |
+
}
|
58 |
+
}
|
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 'both'
|
66 |
+
* @param array $data additional data about the connection to filter against
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
*
|
68 |
+
* @return array( p2p_id => post_id )
|
|
|
|
|
69 |
*/
|
70 |
+
function p2p_get_connected( $post_id, $direction = 'to', $data = array() ) {
|
71 |
+
if ( 'both' == $direction ) {
|
72 |
+
$to = P2P_Connections::get( $post_id, 'to', $data );
|
73 |
+
$from = P2P_Connections::get( $post_id, 'from', $data );
|
74 |
+
$ids = array_merge( $to, array_diff( $from, $to ) );
|
75 |
+
} else {
|
76 |
+
$ids = P2P_Connections::get( $post_id, $direction, $data );
|
77 |
+
}
|
78 |
+
|
79 |
+
return $ids;
|
80 |
}
|
81 |
|
82 |
/**
|
83 |
* See if a certain post is connected to another one
|
84 |
*
|
85 |
+
* @param int $from The first end of the connection
|
86 |
+
* @param int $to The second end of the connection
|
87 |
+
* @param array $data additional data about the connection to filter against
|
88 |
*
|
89 |
* @return bool True if the connection exists, false otherwise
|
90 |
*/
|
91 |
+
function p2p_is_connected( $from, $to, $data = array() ) {
|
92 |
+
$ids = p2p_get_connected( $from, $to, $data );
|
|
|
|
|
|
|
93 |
|
94 |
+
return !empty( $ids );
|
95 |
}
|
96 |
|
97 |
/**
|
98 |
+
* Delete one or more connections
|
99 |
*
|
100 |
+
* @param int|array $p2p_id Connection ids
|
|
|
|
|
|
|
101 |
*
|
102 |
+
* @return int Number of connections deleted
|
|
|
103 |
*/
|
104 |
+
function p2p_delete_connection( $p2p_id ) {
|
105 |
+
return P2P_Connections::delete( $p2p_id );
|
106 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
|
108 |
+
// Allows you to write query_posts( array( 'connected' => 123 ) );
|
109 |
+
class P2P_Query {
|
110 |
|
111 |
+
function init() {
|
112 |
+
add_filter( 'posts_where', array( __CLASS__, 'posts_where' ), 10, 2 );
|
113 |
+
}
|
114 |
|
115 |
+
function posts_where( $where, $wp_query ) {
|
116 |
+
global $wpdb;
|
117 |
|
118 |
+
$map = array(
|
119 |
+
'connected' => 'both',
|
120 |
+
'connected_to' => 'to',
|
121 |
+
'connected_from' => 'from',
|
122 |
+
);
|
|
|
|
|
123 |
|
124 |
+
foreach ( $map as $qv => $direction ) {
|
125 |
+
if ( $id = $wp_query->get( $qv ) ) {
|
126 |
+
$where .= " AND $wpdb->posts.ID IN ( " . implode( ',', p2p_get_connected( $id, $direction ) ) . " )";
|
127 |
+
}
|
128 |
+
}
|
129 |
|
130 |
+
return $where;
|
131 |
+
}
|
|
|
|
|
132 |
}
|
133 |
|
core.php
DELETED
@@ -1,77 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
// Abstraction layer for connection storage
|
4 |
-
|
5 |
-
class Posts2Posts {
|
6 |
-
const TAX = 'p2p';
|
7 |
-
|
8 |
-
function init() {
|
9 |
-
add_action( 'init', array( __CLASS__, 'setup' ) );
|
10 |
-
add_action( 'delete_post', array( __CLASS__, 'delete_post' ) );
|
11 |
-
}
|
12 |
-
|
13 |
-
function setup() {
|
14 |
-
register_taxonomy( self::TAX, 'post', array( 'public' => false ) );
|
15 |
-
}
|
16 |
-
|
17 |
-
function delete_post( $post_id ) {
|
18 |
-
wp_delete_term( self::convert( 'term', $post_id ), self::TAX );
|
19 |
-
}
|
20 |
-
|
21 |
-
function connect( $post_a, $post_b ) {
|
22 |
-
if ( empty( $post_a ) )
|
23 |
-
return;
|
24 |
-
|
25 |
-
$terms = self::convert( 'term', $post_b );
|
26 |
-
|
27 |
-
if ( empty( $terms ) )
|
28 |
-
return;
|
29 |
-
|
30 |
-
wp_set_object_terms( $post_a, $terms, self::TAX, true );
|
31 |
-
}
|
32 |
-
|
33 |
-
function disconnect( $post_a, $post_b ) {
|
34 |
-
if ( empty( $post_a ) )
|
35 |
-
return;
|
36 |
-
|
37 |
-
$terms = self::convert( 'term', $post_b );
|
38 |
-
|
39 |
-
if ( empty( $terms ) )
|
40 |
-
return;
|
41 |
-
|
42 |
-
$list = wp_get_object_terms( $post_a, self::TAX, 'fields=names' );
|
43 |
-
|
44 |
-
wp_set_object_terms( $post_a, array_diff( $list, $terms ), self::TAX );
|
45 |
-
}
|
46 |
-
|
47 |
-
function is_connected( $post_a, $post_b ) {
|
48 |
-
$terms = self::convert( 'term', $post_b );
|
49 |
-
|
50 |
-
return is_object_in_term( $post_a, $terms, self::TAX );
|
51 |
-
}
|
52 |
-
|
53 |
-
function get_connected( $post_id, $direction ) {
|
54 |
-
if ( 'from' == $direction ) {
|
55 |
-
$terms = wp_get_object_terms( $post_id, self::TAX, array( 'fields' => 'names' ) );
|
56 |
-
return self::convert( 'post', $terms );
|
57 |
-
} else {
|
58 |
-
$term = get_term_by( 'slug', reset( self::convert( 'term', $post_id ) ), self::TAX )->term_id;
|
59 |
-
return get_objects_in_term( $term, self::TAX );
|
60 |
-
}
|
61 |
-
}
|
62 |
-
|
63 |
-
// Add a 'p' to avoid confusion with term ids
|
64 |
-
private function convert( $to, $ids ) {
|
65 |
-
$ids = array_filter( (array) $ids );
|
66 |
-
|
67 |
-
if ( 'term' == $to )
|
68 |
-
foreach ( $ids as &$id )
|
69 |
-
$id = 'p' . $id;
|
70 |
-
else
|
71 |
-
foreach ( $ids as &$id )
|
72 |
-
$id = substr( $id, 1 );
|
73 |
-
|
74 |
-
return $ids;
|
75 |
-
}
|
76 |
-
}
|
77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lang/posts-to-posts.pot
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
# Translation of the WordPress plugin Posts 2 Posts 0.3
|
2 |
# Copyright (C) 2010 scribu
|
3 |
# This file is distributed under the same license as the Posts 2 Posts package.
|
4 |
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
|
@@ -6,9 +6,9 @@
|
|
6 |
#, fuzzy
|
7 |
msgid ""
|
8 |
msgstr ""
|
9 |
-
"Project-Id-Version: Posts 2 Posts 0.3
|
10 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/posts-to-posts\n"
|
11 |
-
"POT-Creation-Date: 2010-08-04 20:
|
12 |
"PO-Revision-Date: 2010-MO-DA HO:MI+ZONE\n"
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
1 |
+
# Translation of the WordPress plugin Posts 2 Posts 0.3 by scribu.
|
2 |
# Copyright (C) 2010 scribu
|
3 |
# This file is distributed under the same license as the Posts 2 Posts package.
|
4 |
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
|
6 |
#, fuzzy
|
7 |
msgid ""
|
8 |
msgstr ""
|
9 |
+
"Project-Id-Version: Posts 2 Posts 0.3\n"
|
10 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/posts-to-posts\n"
|
11 |
+
"POT-Creation-Date: 2010-08-04 20:39+0300\n"
|
12 |
"PO-Revision-Date: 2010-MO-DA HO:MI+ZONE\n"
|
13 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
14 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
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 connections between posts of different types
|
7 |
Author URI: http://scribu.net/
|
@@ -10,12 +10,12 @@ Text Domain: posts-to-posts
|
|
10 |
Domain Path: /lang
|
11 |
|
12 |
|
13 |
-
Copyright (
|
14 |
|
15 |
This program is free software; you can redistribute it and/or modify
|
16 |
it under the terms of the GNU General Public License as published by
|
17 |
the Free Software Foundation; either version 3 of the License, or
|
18 |
-
(
|
19 |
|
20 |
This program is distributed in the hope that it will be useful,
|
21 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
@@ -29,15 +29,48 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
29 |
require dirname( __FILE__ ) . '/scb/load.php';
|
30 |
|
31 |
function _p2p_init() {
|
32 |
-
require dirname( __FILE__ ) . '/
|
33 |
require dirname( __FILE__ ) . '/api.php';
|
|
|
|
|
34 |
|
35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
|
37 |
-
|
38 |
-
|
39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
}
|
41 |
}
|
42 |
-
scb_init( '_p2p_init' );
|
43 |
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: Posts 2 Posts
|
4 |
+
Version: 0.4
|
5 |
Plugin Author: scribu
|
6 |
Description: Create connections between posts of different types
|
7 |
Author URI: http://scribu.net/
|
10 |
Domain Path: /lang
|
11 |
|
12 |
|
13 |
+
Copyright (C) 2010 Cristi Burcă (scribu@gmail.com)
|
14 |
|
15 |
This program is free software; you can redistribute it and/or modify
|
16 |
it under the terms of the GNU General Public License as published by
|
17 |
the Free Software Foundation; either version 3 of the License, or
|
18 |
+
(at your option) any later version.
|
19 |
|
20 |
This program is distributed in the hope that it will be useful,
|
21 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
29 |
require dirname( __FILE__ ) . '/scb/load.php';
|
30 |
|
31 |
function _p2p_init() {
|
32 |
+
require dirname( __FILE__ ) . '/storage.php';
|
33 |
require dirname( __FILE__ ) . '/api.php';
|
34 |
+
require dirname( __FILE__ ) . '/ui/ui.php';
|
35 |
+
require dirname( __FILE__ ) . '/ui/boxes.php';
|
36 |
|
37 |
+
P2P_Connections::init( __FILE__ );
|
38 |
+
P2P_Query::init();
|
39 |
+
P2P_Connection_Types::init();
|
40 |
+
P2P_Box_Multiple::init();
|
41 |
+
|
42 |
+
P2P_Migrate::init();
|
43 |
+
}
|
44 |
+
scb_init( '_p2p_init' );
|
45 |
+
|
46 |
+
|
47 |
+
class P2P_Migrate {
|
48 |
+
|
49 |
+
function init() {
|
50 |
+
add_action( 'admin_notices', array( __CLASS__, 'migrate' ) );
|
51 |
+
}
|
52 |
+
|
53 |
+
function migrate() {
|
54 |
+
if ( !isset( $_GET['migrate_p2p'] ) || !current_user_can( 'administrator' ) )
|
55 |
+
return;
|
56 |
|
57 |
+
$tax = 'p2p';
|
58 |
+
|
59 |
+
register_taxonomy( $tax, 'post', array( 'public' => false ) );
|
60 |
+
|
61 |
+
$count = 0;
|
62 |
+
foreach ( get_terms( $tax ) as $term ) {
|
63 |
+
$post_b = (int) substr( $term->slug, 1 );
|
64 |
+
$post_a = get_objects_in_term( $term->term_id, $tax );
|
65 |
+
|
66 |
+
p2p_connect( $post_a, $post_b );
|
67 |
+
|
68 |
+
wp_delete_term( $term->term_id, $tax );
|
69 |
+
|
70 |
+
$count += count( $post_a );
|
71 |
+
}
|
72 |
+
|
73 |
+
printf( "<div class='updated'><p>Migrated %d connections.</p></div>", $count );
|
74 |
}
|
75 |
}
|
|
|
76 |
|
readme.txt
CHANGED
@@ -4,13 +4,13 @@ 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.0
|
7 |
-
Stable tag: 0.
|
8 |
|
9 |
Create connections between posts
|
10 |
|
11 |
== Description ==
|
12 |
|
13 |
-
This plugin allows you to create relationships between posts of
|
14 |
|
15 |
To register a connection type, add this code in your theme's functions.php file:
|
16 |
|
@@ -19,14 +19,13 @@ function my_connection_types() {
|
|
19 |
if ( !function_exists('p2p_register_connection_type') )
|
20 |
return;
|
21 |
|
22 |
-
p2p_register_connection_type('
|
23 |
-
p2p_register_connection_type('library', 'book');
|
24 |
}
|
25 |
add_action('init', 'my_connection_types', 100);
|
26 |
`
|
27 |
<br>
|
28 |
|
29 |
-
Links: [API](http://plugins.trac.wordpress.org/browser/posts-to-posts/
|
30 |
|
31 |
== Installation ==
|
32 |
|
@@ -50,6 +49,14 @@ Make sure your host is running PHP 5. The only foolproof way to do this is to ad
|
|
50 |
|
51 |
== Changelog ==
|
52 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
= 0.3 =
|
54 |
* store connections using a taxonomy instead of postmeta
|
55 |
* [more info](http://scribu.net/wordpress/posts-to-posts/p2p-0-3.html)
|
4 |
Tags: cms, custom post types, relationships, many-to-many
|
5 |
Requires at least: 3.0
|
6 |
Tested up to: 3.0
|
7 |
+
Stable tag: 0.4
|
8 |
|
9 |
Create connections between posts
|
10 |
|
11 |
== Description ==
|
12 |
|
13 |
+
This plugin allows you to create many-to-many relationships between posts of all types.
|
14 |
|
15 |
To register a connection type, add this code in your theme's functions.php file:
|
16 |
|
19 |
if ( !function_exists('p2p_register_connection_type') )
|
20 |
return;
|
21 |
|
22 |
+
p2p_register_connection_type( 'post', 'page' );
|
|
|
23 |
}
|
24 |
add_action('init', 'my_connection_types', 100);
|
25 |
`
|
26 |
<br>
|
27 |
|
28 |
+
Links: [API](http://plugins.trac.wordpress.org/browser/posts-to-posts/trunk/api.php) | [Plugin News](http://scribu.net/wordpress/posts-to-posts) | [Author's Site](http://scribu.net)
|
29 |
|
30 |
== Installation ==
|
31 |
|
49 |
|
50 |
== Changelog ==
|
51 |
|
52 |
+
= 0.4 =
|
53 |
+
* introduced 'connected_from', 'connected_to', 'connected' vars to WP_Query
|
54 |
+
* replaced $reciprocal with $data as the third argument
|
55 |
+
* p2p_register_connection_type() accepts an associative array as arguments
|
56 |
+
* removed p2p_list_connected()
|
57 |
+
* added p2p_delete_connection()
|
58 |
+
* [more info](http://scribu.net/wordpress/posts-to-posts/p2p-0-4.html)
|
59 |
+
|
60 |
= 0.3 =
|
61 |
* store connections using a taxonomy instead of postmeta
|
62 |
* [more info](http://scribu.net/wordpress/posts-to-posts/p2p-0-3.html)
|
scb/AdminPage.php
CHANGED
@@ -35,9 +35,6 @@ abstract class scbAdminPage {
|
|
35 |
// l10n
|
36 |
protected $textdomain;
|
37 |
|
38 |
-
// Formdata used for filling the form elements
|
39 |
-
protected $formdata = array();
|
40 |
-
|
41 |
|
42 |
// ____________REGISTRATION COMPONENT____________
|
43 |
|
@@ -85,10 +82,8 @@ abstract class scbAdminPage {
|
|
85 |
|
86 |
// Constructor
|
87 |
function __construct( $file, $options = NULL ) {
|
88 |
-
if (
|
89 |
$this->options = $options;
|
90 |
-
$this->formdata = $this->options->get();
|
91 |
-
}
|
92 |
|
93 |
$this->file = $file;
|
94 |
$this->plugin_url = plugin_dir_url( $file );
|
@@ -147,16 +142,18 @@ abstract class scbAdminPage {
|
|
147 |
|
148 |
check_admin_referer( $this->nonce );
|
149 |
|
150 |
-
|
151 |
-
|
152 |
-
|
|
|
|
|
|
|
153 |
|
154 |
$new_data = stripslashes_deep( $new_data );
|
155 |
|
156 |
-
$
|
157 |
|
158 |
-
|
159 |
-
$this->options->set( $this->formdata );
|
160 |
|
161 |
$this->admin_msg();
|
162 |
}
|
@@ -286,8 +283,8 @@ abstract class scbAdminPage {
|
|
286 |
}
|
287 |
|
288 |
function input( $args, $formdata = array() ) {
|
289 |
-
if ( empty( $formdata ) )
|
290 |
-
$formdata = $this->
|
291 |
|
292 |
if ( isset( $args['name_tree'] ) ) {
|
293 |
$tree = ( array ) $args['name_tree'];
|
@@ -383,7 +380,9 @@ abstract class scbAdminPage {
|
|
383 |
if ( is_object( $screen ) )
|
384 |
$screen = $screen->id;
|
385 |
|
386 |
-
|
|
|
|
|
387 |
return $actual_help;
|
388 |
|
389 |
return $help;
|
35 |
// l10n
|
36 |
protected $textdomain;
|
37 |
|
|
|
|
|
|
|
38 |
|
39 |
// ____________REGISTRATION COMPONENT____________
|
40 |
|
82 |
|
83 |
// Constructor
|
84 |
function __construct( $file, $options = NULL ) {
|
85 |
+
if ( is_a( $options, 'scbOptions' ) )
|
86 |
$this->options = $options;
|
|
|
|
|
87 |
|
88 |
$this->file = $file;
|
89 |
$this->plugin_url = plugin_dir_url( $file );
|
142 |
|
143 |
check_admin_referer( $this->nonce );
|
144 |
|
145 |
+
if ( !isset($this->options) ) {
|
146 |
+
trigger_error('options handler not set', E_USER_WARNING);
|
147 |
+
return false;
|
148 |
+
}
|
149 |
+
|
150 |
+
$new_data = scbUtil::array_extract( $_POST, array_keys( $this->options->get_defaults() ) );
|
151 |
|
152 |
$new_data = stripslashes_deep( $new_data );
|
153 |
|
154 |
+
$new_data = $this->validate( $new_data, $this->options->get() );
|
155 |
|
156 |
+
$this->options->set( $new_data );
|
|
|
157 |
|
158 |
$this->admin_msg();
|
159 |
}
|
283 |
}
|
284 |
|
285 |
function input( $args, $formdata = array() ) {
|
286 |
+
if ( empty( $formdata ) && isset( $this->options ) )
|
287 |
+
$formdata = $this->options->get();
|
288 |
|
289 |
if ( isset( $args['name_tree'] ) ) {
|
290 |
$tree = ( array ) $args['name_tree'];
|
380 |
if ( is_object( $screen ) )
|
381 |
$screen = $screen->id;
|
382 |
|
383 |
+
$actual_help = $this->page_help();
|
384 |
+
|
385 |
+
if ( $screen == $this->pagehook && $actual_help )
|
386 |
return $actual_help;
|
387 |
|
388 |
return $help;
|
scb/BoxesPage.php
CHANGED
@@ -43,17 +43,43 @@ abstract class scbBoxesPage extends scbAdminPage {
|
|
43 |
function default_css() {
|
44 |
?>
|
45 |
<style type="text/css">
|
46 |
-
.postbox-container + .postbox-container {
|
47 |
-
|
48 |
-
|
49 |
-
.
|
50 |
-
|
51 |
-
|
52 |
-
.inside
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
</style>
|
58 |
<?php
|
59 |
}
|
@@ -121,9 +147,6 @@ abstract class scbBoxesPage extends scbAdminPage {
|
|
121 |
if ( method_exists( $this, $handler ) )
|
122 |
call_user_func_array( array( $this, $handler ), $args );
|
123 |
}
|
124 |
-
|
125 |
-
if ( $this->options )
|
126 |
-
$this->formdata = $this->options->get();
|
127 |
}
|
128 |
|
129 |
function columns( $columns ) {
|
43 |
function default_css() {
|
44 |
?>
|
45 |
<style type="text/css">
|
46 |
+
.postbox-container + .postbox-container {
|
47 |
+
margin-left: 18px;
|
48 |
+
}
|
49 |
+
.postbox-container {
|
50 |
+
padding-right: 0;
|
51 |
+
}
|
52 |
+
.inside {
|
53 |
+
clear: both;
|
54 |
+
overflow: hidden;
|
55 |
+
padding: 10px 10px 0 !important;
|
56 |
+
}
|
57 |
+
.inside table {
|
58 |
+
margin: 0 !important;
|
59 |
+
padding: 0 !important;
|
60 |
+
}
|
61 |
+
.inside table td {
|
62 |
+
vertical-align: middle !important;
|
63 |
+
}
|
64 |
+
.inside table .regular-text {
|
65 |
+
width: 100% !important;
|
66 |
+
}
|
67 |
+
.inside .form-table th {
|
68 |
+
width: 30%;
|
69 |
+
max-width: 200px;
|
70 |
+
padding: 10px 0 !important;
|
71 |
+
}
|
72 |
+
.inside .widefat .check-column {
|
73 |
+
padding-bottom: 7px !important;
|
74 |
+
}
|
75 |
+
.inside p,
|
76 |
+
.inside table {
|
77 |
+
margin: 0 0 10px !important;
|
78 |
+
}
|
79 |
+
.inside p.submit {
|
80 |
+
float: left !important;
|
81 |
+
padding: 0 !important;
|
82 |
+
}
|
83 |
</style>
|
84 |
<?php
|
85 |
}
|
147 |
if ( method_exists( $this, $handler ) )
|
148 |
call_user_func_array( array( $this, $handler ), $args );
|
149 |
}
|
|
|
|
|
|
|
150 |
}
|
151 |
|
152 |
function columns( $columns ) {
|
scb/QueryManipulation.php
CHANGED
@@ -19,7 +19,7 @@ class scbQueryManipulation {
|
|
19 |
$this->callback = $callback;
|
20 |
|
21 |
$this->enable();
|
22 |
-
|
23 |
if ( !$once )
|
24 |
return;
|
25 |
|
19 |
$this->callback = $callback;
|
20 |
|
21 |
$this->enable();
|
22 |
+
|
23 |
if ( !$once )
|
24 |
return;
|
25 |
|
scb/Rewrite.php
DELETED
@@ -1,24 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
// Helper class for modifying the rewrite rules
|
4 |
-
abstract class scbRewrite {
|
5 |
-
|
6 |
-
public function __construct( $plugin_file = '' ) {
|
7 |
-
|
8 |
-
add_action( 'init', array( $this, 'generate' ) );
|
9 |
-
add_action( 'generate_rewrite_rules', array( $this, 'generate' ) );
|
10 |
-
|
11 |
-
if ( $plugin_file )
|
12 |
-
scbUtil::add_activation_hook( $plugin_file, array( __CLASS__, 'flush' ) );
|
13 |
-
}
|
14 |
-
|
15 |
-
// This is where the actual code goes
|
16 |
-
abstract public function generate();
|
17 |
-
|
18 |
-
static public function flush() {
|
19 |
-
global $wp_rewrite;
|
20 |
-
|
21 |
-
$wp_rewrite->flush_rules();
|
22 |
-
}
|
23 |
-
}
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
scb/Util.php
CHANGED
@@ -117,7 +117,7 @@ class scbUtil {
|
|
117 |
|
118 |
|
119 |
if ( ! function_exists( 'html' ) ):
|
120 |
-
function html($tag, $attributes = array(), $content = '') {
|
121 |
if ( is_array( $attributes ) ) {
|
122 |
$closing = $tag;
|
123 |
foreach ( $attributes as $key => $value ) {
|
@@ -125,7 +125,7 @@ function html($tag, $attributes = array(), $content = '') {
|
|
125 |
}
|
126 |
} else {
|
127 |
$content = $attributes;
|
128 |
-
list($closing) = explode(' ', $tag, 2);
|
129 |
}
|
130 |
|
131 |
return "<{$tag}>{$content}</{$closing}>";
|
@@ -145,21 +145,6 @@ endif;
|
|
145 |
|
146 |
//_____Compatibility layer_____
|
147 |
|
148 |
-
|
149 |
-
// WP < 3.0
|
150 |
-
if ( ! function_exists( '__return_false' ) ) :
|
151 |
-
function __return_false() {
|
152 |
-
return false;
|
153 |
-
}
|
154 |
-
endif;
|
155 |
-
|
156 |
-
// WP < ?
|
157 |
-
if ( ! function_exists( '__return_true' ) ) :
|
158 |
-
function __return_true() {
|
159 |
-
return true;
|
160 |
-
}
|
161 |
-
endif;
|
162 |
-
|
163 |
// WP < ?
|
164 |
if ( ! function_exists( 'set_post_field' ) ) :
|
165 |
function set_post_field( $field, $value, $post_id ) {
|
117 |
|
118 |
|
119 |
if ( ! function_exists( 'html' ) ):
|
120 |
+
function html( $tag, $attributes = array(), $content = '' ) {
|
121 |
if ( is_array( $attributes ) ) {
|
122 |
$closing = $tag;
|
123 |
foreach ( $attributes as $key => $value ) {
|
125 |
}
|
126 |
} else {
|
127 |
$content = $attributes;
|
128 |
+
list( $closing ) = explode(' ', $tag, 2);
|
129 |
}
|
130 |
|
131 |
return "<{$tag}>{$content}</{$closing}>";
|
145 |
|
146 |
//_____Compatibility layer_____
|
147 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
148 |
// WP < ?
|
149 |
if ( ! function_exists( 'set_post_field' ) ) :
|
150 |
function set_post_field( $field, $value, $post_id ) {
|
scb/load.php
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
$GLOBALS['_scb_data'] = array(
|
4 |
'scbUtil', 'scbOptions', 'scbForms', 'scbTable',
|
5 |
'scbWidget', 'scbAdminPage', 'scbBoxesPage',
|
6 |
-
'scbQueryManipulation', '
|
7 |
) );
|
8 |
|
9 |
if ( !class_exists( 'scbLoad4' ) ) :
|
1 |
<?php
|
2 |
|
3 |
+
$GLOBALS['_scb_data'] = array( 25, __FILE__, array(
|
4 |
'scbUtil', 'scbOptions', 'scbForms', 'scbTable',
|
5 |
'scbWidget', 'scbAdminPage', 'scbBoxesPage',
|
6 |
+
'scbQueryManipulation', 'scbCron',
|
7 |
) );
|
8 |
|
9 |
if ( !class_exists( 'scbLoad4' ) ) :
|
storage.php
ADDED
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class P2P_Connections {
|
4 |
+
|
5 |
+
function init( $file ) {
|
6 |
+
$table = new scbTable( 'p2p', $file, "
|
7 |
+
p2p_id bigint(20) unsigned NOT NULL auto_increment,
|
8 |
+
p2p_from bigint(20) unsigned NOT NULL,
|
9 |
+
p2p_to bigint(20) unsigned NOT NULL,
|
10 |
+
PRIMARY KEY (p2p_id),
|
11 |
+
KEY p2p_from (p2p_from),
|
12 |
+
KEY p2p_to (p2p_to)
|
13 |
+
" );
|
14 |
+
|
15 |
+
$table2 = new scbTable( 'p2pmeta', $file, "
|
16 |
+
meta_id bigint(20) unsigned NOT NULL auto_increment,
|
17 |
+
p2p_id bigint(20) unsigned NOT NULL default '0',
|
18 |
+
meta_key varchar(255) default NULL,
|
19 |
+
meta_value longtext,
|
20 |
+
PRIMARY KEY (meta_id),
|
21 |
+
KEY p2p_id (p2p_id),
|
22 |
+
KEY meta_key (meta_key)
|
23 |
+
" );
|
24 |
+
|
25 |
+
// FORCE UPDATE
|
26 |
+
#add_action('init', array($table, 'install'));
|
27 |
+
#add_action('init', array($table2, 'install'));
|
28 |
+
|
29 |
+
add_action( 'delete_post', array( __CLASS__, 'delete_post' ) );
|
30 |
+
}
|
31 |
+
|
32 |
+
function delete_post( $post_id ) {
|
33 |
+
self::disconnect( $post_id, 'from' );
|
34 |
+
self::disconnect( $post_id, 'to' );
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Get a list of connections, given a certain post id
|
39 |
+
*
|
40 |
+
* @param int $from post id
|
41 |
+
* @param int|string $to post id or direction: 'from' or 'to'
|
42 |
+
* @param array $data additional data about the connection to filter against
|
43 |
+
*
|
44 |
+
* @return array( p2p_id => post_id ) if $to is string
|
45 |
+
* @return array( p2p_id ) if $to is int
|
46 |
+
*/
|
47 |
+
function get( $from, $to, $data = array(), $_return_p2p_ids = false ) {
|
48 |
+
global $wpdb;
|
49 |
+
|
50 |
+
$select = "p2p_id";
|
51 |
+
$where = "";
|
52 |
+
|
53 |
+
switch ( $to ) {
|
54 |
+
case 'from':
|
55 |
+
$select .= $_return_p2p_ids ? '' : ', p2p_to AS post_id';
|
56 |
+
$where .= $wpdb->prepare( "p2p_from = %d", $from );
|
57 |
+
break;
|
58 |
+
case 'to':
|
59 |
+
$select .= $_return_p2p_ids ? '' : ', p2p_from AS post_id';
|
60 |
+
$where .= $wpdb->prepare( "p2p_to = %d", $from );
|
61 |
+
break;
|
62 |
+
default:
|
63 |
+
$where .= $wpdb->prepare( "p2p_from = %d AND p2p_to = %d", $from, $to );
|
64 |
+
$_return_p2p_ids = true;
|
65 |
+
}
|
66 |
+
|
67 |
+
if ( !empty( $data ) ) {
|
68 |
+
$clauses = array();
|
69 |
+
foreach ( $data as $key => $value ) {
|
70 |
+
$clauses[] = $wpdb->prepare( "WHEN %s THEN meta_value = %s ", $key, $value );
|
71 |
+
}
|
72 |
+
|
73 |
+
$where .= " AND p2p_id IN (
|
74 |
+
SELECT p2p_id
|
75 |
+
FROM $wpdb->p2pmeta
|
76 |
+
WHERE CASE meta_key
|
77 |
+
" . implode( "\n", $clauses ) . "
|
78 |
+
END
|
79 |
+
GROUP BY p2p_id HAVING COUNT(p2p_id) = " . count($data) . "
|
80 |
+
)";
|
81 |
+
}
|
82 |
+
|
83 |
+
$query = "SELECT $select FROM $wpdb->p2p WHERE $where";
|
84 |
+
|
85 |
+
if ( $_return_p2p_ids )
|
86 |
+
return $wpdb->get_col( $query );
|
87 |
+
|
88 |
+
$results = $wpdb->get_results( $query );
|
89 |
+
|
90 |
+
$r = array();
|
91 |
+
foreach ( $results as $row )
|
92 |
+
$r[ $row->p2p_id ] = $row->post_id;
|
93 |
+
|
94 |
+
return $r;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Connect two posts
|
99 |
+
*
|
100 |
+
* @param int $from post id
|
101 |
+
* @param int $to post id
|
102 |
+
* @param array $data additional data about the connection
|
103 |
+
*
|
104 |
+
* @return int|bool connection id or False on failure
|
105 |
+
*/
|
106 |
+
function connect( $from, $to, $data = array() ) {
|
107 |
+
global $wpdb;
|
108 |
+
|
109 |
+
$from = absint( $from );
|
110 |
+
$to = absint( $to );
|
111 |
+
|
112 |
+
if ( !$from || !$to )
|
113 |
+
return false;
|
114 |
+
|
115 |
+
$p2p_ids = self::get( $from, $to, $data, true );
|
116 |
+
|
117 |
+
if ( !empty( $p2p_ids ) )
|
118 |
+
return $p2p_ids[0];
|
119 |
+
|
120 |
+
$wpdb->insert( $wpdb->p2p, array( 'p2p_from' => $from, 'p2p_to' => $to ), '%d' );
|
121 |
+
|
122 |
+
$p2p_id = $wpdb->insert_id;
|
123 |
+
|
124 |
+
foreach ( $data as $key => $value )
|
125 |
+
p2p_add_meta( $p2p_id, $key, $value );
|
126 |
+
|
127 |
+
return $p2p_id;
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Disconnect two posts
|
132 |
+
*
|
133 |
+
* @param int $from post id
|
134 |
+
* @param int|string $to post id or direction: 'from' or 'to'
|
135 |
+
* @param array $data additional data about the connection to filter against
|
136 |
+
*
|
137 |
+
* @return int Number of connections deleted
|
138 |
+
*/
|
139 |
+
function disconnect( $from, $to, $data = array() ) {
|
140 |
+
return self::delete( self::get( $from, $to, $data, true ) );
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Delete one or more connections
|
145 |
+
*
|
146 |
+
* @param int|array $p2p_id Connection ids
|
147 |
+
*
|
148 |
+
* @return int Number of connections deleted
|
149 |
+
*/
|
150 |
+
function delete( $p2p_id ) {
|
151 |
+
global $wpdb;
|
152 |
+
|
153 |
+
if ( empty( $p2p_id ) )
|
154 |
+
return 0;
|
155 |
+
|
156 |
+
$p2p_ids = array_map( 'absint', (array) $p2p_id );
|
157 |
+
|
158 |
+
$where = "WHERE p2p_id IN (" . implode( ',', $p2p_ids ) . ")";
|
159 |
+
|
160 |
+
$wpdb->query( "DELETE FROM $wpdb->p2p $where" );
|
161 |
+
$wpdb->query( "DELETE FROM $wpdb->p2pmeta $where" );
|
162 |
+
|
163 |
+
return count( $p2p_ids );
|
164 |
+
}
|
165 |
+
}
|
166 |
+
|
167 |
+
|
168 |
+
function p2p_get_meta($p2p_id, $key, $single = false) {
|
169 |
+
return get_metadata('p2p', $p2p_id, $key, $single);
|
170 |
+
}
|
171 |
+
|
172 |
+
function p2p_update_meta($p2p_id, $meta_key, $meta_value, $prev_value = '') {
|
173 |
+
return update_metadata('p2p', $p2p_id, $meta_key, $meta_value, $prev_value);
|
174 |
+
}
|
175 |
+
|
176 |
+
function p2p_add_meta($p2p_id, $meta_key, $meta_value, $unique = false) {
|
177 |
+
return add_metadata('p2p', $p2p_id, $meta_key, $meta_value, $unique);
|
178 |
+
}
|
179 |
+
|
180 |
+
function p2p_delete_meta($p2p_id, $meta_key, $meta_value = '') {
|
181 |
+
return delete_metadata('p2p', $p2p_id, $meta_key, $meta_value);
|
182 |
+
}
|
183 |
+
|
{admin → ui}/admin.js
RENAMED
@@ -49,7 +49,7 @@ jQuery(document).ready(function($) {
|
|
49 |
var $self = $(this);
|
50 |
$metabox = $self.parents('.p2p_metabox'),
|
51 |
$results = $metabox.find('.p2p_results'),
|
52 |
-
post_type = $self.attr('name').
|
53 |
old_value = '',
|
54 |
$spinner = $metabox.find('.waiting');
|
55 |
|
49 |
var $self = $(this);
|
50 |
$metabox = $self.parents('.p2p_metabox'),
|
51 |
$results = $metabox.find('.p2p_results'),
|
52 |
+
post_type = $self.attr('name').replace('p2p_search_', ''),
|
53 |
old_value = '',
|
54 |
$spinner = $metabox.find('.waiting');
|
55 |
|
ui/boxes.php
ADDED
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class P2P_Box_Multiple extends P2P_Box {
|
4 |
+
|
5 |
+
protected $meta_keys = array();
|
6 |
+
|
7 |
+
function init() {
|
8 |
+
add_action( 'admin_print_styles-post.php', array( __CLASS__, 'scripts' ) );
|
9 |
+
add_action( 'admin_print_styles-post-new.php', array( __CLASS__, 'scripts' ) );
|
10 |
+
|
11 |
+
add_action( 'wp_ajax_p2p_search', array( __CLASS__, 'ajax_search' ) );
|
12 |
+
}
|
13 |
+
|
14 |
+
function scripts() {
|
15 |
+
wp_enqueue_script( 'p2p-admin-js', plugins_url( 'ui.js', __FILE__ ), array( 'jquery' ), '0.4-alpha6', true );
|
16 |
+
|
17 |
+
?>
|
18 |
+
<style type="text/css">
|
19 |
+
.p2p_connected {margin: 10px 4px}
|
20 |
+
.p2p_results {margin: -5px 6px 10px}
|
21 |
+
.p2p_metabox .waiting {vertical-align: -.4em}
|
22 |
+
</style>
|
23 |
+
<?php
|
24 |
+
}
|
25 |
+
|
26 |
+
function save( $post_a, $data ) {
|
27 |
+
if ( !empty( $data['all'] ) )
|
28 |
+
p2p_delete_connection( array_diff( $data['all'], (array) @$data['enabled'] ) );
|
29 |
+
|
30 |
+
foreach ( explode( ',', $data[ 'ids' ] ) as $i => $post_b ) {
|
31 |
+
$meta = array();
|
32 |
+
foreach ( $this->meta_keys as $meta_key ) {
|
33 |
+
$meta_value = $data[ $meta_key ][ $i ];
|
34 |
+
|
35 |
+
if ( empty( $meta_value ) )
|
36 |
+
continue;
|
37 |
+
|
38 |
+
$meta[ $meta_key ] = $meta_value;
|
39 |
+
}
|
40 |
+
|
41 |
+
if ( $this->reversed )
|
42 |
+
p2p_connect( $post_b, $post_a, $meta );
|
43 |
+
else
|
44 |
+
p2p_connect( $post_a, $post_b, $meta );
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
function box( $post_id ) {
|
49 |
+
$connected_ids = $this->get_connected_ids( $post_id );
|
50 |
+
|
51 |
+
foreach ( array_keys( $connected_ids ) as $p2p_id ) { ?>
|
52 |
+
<input type="hidden" name="<?php echo $this->input_name( array( 'all', '' ) ); ?>" value="<?php echo $p2p_id; ?>">
|
53 |
+
<?php } ?>
|
54 |
+
|
55 |
+
<div class="p2p_metabox">
|
56 |
+
<div class="hide-if-no-js checkboxes">
|
57 |
+
<ul class="p2p_connected">
|
58 |
+
<?php if ( empty( $connected_ids ) ) { ?>
|
59 |
+
<li class="howto"><?php _e( 'No connections.', 'posts-to-posts' ); ?></li>
|
60 |
+
<?php } else {
|
61 |
+
foreach ( $connected_ids as $p2p_id => $post_b ) {
|
62 |
+
$this->connection_template( $post_b, $p2p_id );
|
63 |
+
}
|
64 |
+
} ?>
|
65 |
+
</ul>
|
66 |
+
|
67 |
+
<?php echo html( 'p class="p2p_search"',
|
68 |
+
scbForms::input( array(
|
69 |
+
'type' => 'text',
|
70 |
+
'name' => 'p2p_search_' . $this->to,
|
71 |
+
'desc' => __( 'Search', 'posts-to-posts' ) . ':',
|
72 |
+
'desc_pos' => 'before',
|
73 |
+
'extra' => array( 'autocomplete' => 'off' ),
|
74 |
+
) )
|
75 |
+
. '<img alt="" src="' . admin_url( 'images/wpspin_light.gif' ) . '" class="waiting" style="display: none;">'
|
76 |
+
); ?>
|
77 |
+
|
78 |
+
<ul class="p2p_results"></ul>
|
79 |
+
<p class="howto"><?php _e( 'Start typing name of connected post type and click on it if you want to connect it.', 'posts-to-posts' ); ?></p>
|
80 |
+
</div>
|
81 |
+
|
82 |
+
<div class="hide-if-js">
|
83 |
+
<?php echo scbForms::input( array(
|
84 |
+
'type' => 'text',
|
85 |
+
'name' => $this->input_name( 'ids' ),
|
86 |
+
'value' => '',
|
87 |
+
'extra' => array( 'class' => 'p2p_to_connect' ),
|
88 |
+
) ); ?>
|
89 |
+
<p class="howto"><?php _e( 'Enter IDs of posts to connect, separated by commas.', 'posts-to-posts' ); ?></p>
|
90 |
+
</div>
|
91 |
+
|
92 |
+
<?php // TODO: move to footer, to avoid $_POST polution ?>
|
93 |
+
<div style="display:none" class="connection-template">
|
94 |
+
<?php $this->connection_template(); ?>
|
95 |
+
</div>
|
96 |
+
</div>
|
97 |
+
<?php
|
98 |
+
}
|
99 |
+
|
100 |
+
function connection_template( $post_id = 0, $p2p_id = 0 ) {
|
101 |
+
if ( $post_id ) {
|
102 |
+
$post_title = get_the_title( $post_id );
|
103 |
+
} else {
|
104 |
+
$post_id = '%post_id%';
|
105 |
+
$post_title = '%post_title%';
|
106 |
+
}
|
107 |
+
|
108 |
+
?>
|
109 |
+
<li>
|
110 |
+
<label>
|
111 |
+
<input type="checkbox" checked="checked" name="<?php echo $this->input_name( array( 'enabled', '' ) ); ?>" value="<?php echo $p2p_id; ?>">
|
112 |
+
<?php echo $post_title; ?>
|
113 |
+
</label>
|
114 |
+
</li>
|
115 |
+
<?php
|
116 |
+
}
|
117 |
+
|
118 |
+
protected function get_connected_ids( $post_id ) {
|
119 |
+
$connected_posts = p2p_get_connected( $post_id, $this->direction );
|
120 |
+
|
121 |
+
if ( empty( $connected_posts ) )
|
122 |
+
return array();
|
123 |
+
|
124 |
+
$args = array(
|
125 |
+
'post__in' => $connected_posts,
|
126 |
+
'post_type'=> $this->to,
|
127 |
+
'post_status' => 'any',
|
128 |
+
'nopaging' => true,
|
129 |
+
'suppress_filters' => false,
|
130 |
+
);
|
131 |
+
|
132 |
+
$post_ids = scbUtil::array_pluck( get_posts($args), 'ID' );
|
133 |
+
|
134 |
+
return array_intersect( $connected_posts, $post_ids ); // to preserve p2p_id keys
|
135 |
+
}
|
136 |
+
|
137 |
+
function ajax_search() {
|
138 |
+
$post_type_name = $_GET['post_type'];
|
139 |
+
|
140 |
+
add_filter( 'posts_search', array( __CLASS__, 'only_search_by_title' ) );
|
141 |
+
|
142 |
+
$args = array(
|
143 |
+
's' => $_GET['q'],
|
144 |
+
'post_type' => $post_type_name,
|
145 |
+
'post_status' => 'any',
|
146 |
+
'posts_per_page' => 5,
|
147 |
+
'order' => 'ASC',
|
148 |
+
'orderby' => 'title',
|
149 |
+
'suppress_filters' => false,
|
150 |
+
'update_post_term_cache' => false,
|
151 |
+
'update_post_meta_cache' => false
|
152 |
+
);
|
153 |
+
|
154 |
+
$posts = get_posts( $args );
|
155 |
+
|
156 |
+
$results = array();
|
157 |
+
foreach ( $posts as $post )
|
158 |
+
$results[ $post->ID ] = $post->post_title;
|
159 |
+
|
160 |
+
die( json_encode( $results ) );
|
161 |
+
}
|
162 |
+
|
163 |
+
function only_search_by_title( $sql ) {
|
164 |
+
remove_filter( current_filter(), array( __CLASS__, __FUNCTION__ ) );
|
165 |
+
|
166 |
+
list( $sql ) = explode( ' OR ', $sql, 2 );
|
167 |
+
|
168 |
+
return $sql . '))';
|
169 |
+
}
|
170 |
+
}
|
171 |
+
|
ui/ui.js
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(document).ready(function($) {
|
2 |
+
$('.p2p_results').delegate('a', 'click', function() {
|
3 |
+
var $self = $(this);
|
4 |
+
$metabox = $self.parents('.p2p_metabox'),
|
5 |
+
$list = $metabox.find('.p2p_connected'),
|
6 |
+
post_id = $self.attr('name');
|
7 |
+
|
8 |
+
$list.append(
|
9 |
+
$metabox.find('.connection-template').html()
|
10 |
+
.replace( '%post_id%', post_id )
|
11 |
+
.replace( '%post_title%', $self.html() )
|
12 |
+
);
|
13 |
+
|
14 |
+
$metabox.find('.p2p_connected .howto').remove();
|
15 |
+
|
16 |
+
var $connected = $metabox.find('.p2p_to_connect');
|
17 |
+
|
18 |
+
$connected.val( $connected.val() + post_id + ',' );
|
19 |
+
|
20 |
+
return false;
|
21 |
+
});
|
22 |
+
|
23 |
+
var delayed = undefined;
|
24 |
+
|
25 |
+
$('.p2p_search :text').keyup(function() {
|
26 |
+
|
27 |
+
if ( delayed != undefined )
|
28 |
+
clearTimeout(delayed);
|
29 |
+
|
30 |
+
var $self = $(this);
|
31 |
+
$metabox = $self.parents('.p2p_metabox'),
|
32 |
+
$results = $metabox.find('.p2p_results'),
|
33 |
+
post_type = $self.attr('name').replace('p2p_search_', ''),
|
34 |
+
old_value = '',
|
35 |
+
$spinner = $metabox.find('.waiting');
|
36 |
+
|
37 |
+
var delayed = setTimeout(function() {
|
38 |
+
if ( !$self.val().length ) {
|
39 |
+
$results.html('');
|
40 |
+
return;
|
41 |
+
}
|
42 |
+
|
43 |
+
if ( $self.val() == old_value )
|
44 |
+
return;
|
45 |
+
old_value = $self.val();
|
46 |
+
|
47 |
+
$spinner.show();
|
48 |
+
$.getJSON(ajaxurl, {action: 'p2p_search', q: $self.val(), post_type: post_type}, function(data) {
|
49 |
+
$spinner.hide();
|
50 |
+
|
51 |
+
$results.html('');
|
52 |
+
|
53 |
+
$.each(data, function(id, title) {
|
54 |
+
$results.append('<li><a href="#" name="' + id + '">' + title + '</a></li>');
|
55 |
+
});
|
56 |
+
});
|
57 |
+
}, 400);
|
58 |
+
});
|
59 |
+
});
|
60 |
+
|
ui/ui.php
ADDED
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class P2P_Box {
|
4 |
+
|
5 |
+
protected $reversed;
|
6 |
+
protected $direction;
|
7 |
+
|
8 |
+
private $box_id;
|
9 |
+
private $input;
|
10 |
+
|
11 |
+
abstract function save( $post_id, $data );
|
12 |
+
abstract function box( $post_id );
|
13 |
+
|
14 |
+
protected function input_name( $name ) {
|
15 |
+
return $this->input->get_name( $name );
|
16 |
+
}
|
17 |
+
|
18 |
+
|
19 |
+
// Internal stuff
|
20 |
+
|
21 |
+
|
22 |
+
public function __construct( $args, $reversed, $box_id ) {
|
23 |
+
foreach ( $args as $key => $value )
|
24 |
+
$this->$key = $value;
|
25 |
+
|
26 |
+
$this->box_id = $box_id;
|
27 |
+
$this->reversed = $reversed;
|
28 |
+
|
29 |
+
$this->input = new p2pInput( array( 'p2p', $box_id ) );
|
30 |
+
|
31 |
+
$this->direction = $this->reversed ? 'to' : 'from';
|
32 |
+
|
33 |
+
if ( $this->reversed )
|
34 |
+
list( $this->to, $this->from ) = array( $this->from, $this->to );
|
35 |
+
}
|
36 |
+
|
37 |
+
function _register( $from ) {
|
38 |
+
$title = $this->title;
|
39 |
+
|
40 |
+
if ( empty( $title ) )
|
41 |
+
$title = get_post_type_object( $this->to )->labels->name;
|
42 |
+
|
43 |
+
add_meta_box(
|
44 |
+
'p2p-connections-' . $this->box_id,
|
45 |
+
$title,
|
46 |
+
array( $this, '_box' ),
|
47 |
+
$from,
|
48 |
+
'side',
|
49 |
+
'default'
|
50 |
+
);
|
51 |
+
}
|
52 |
+
|
53 |
+
function _save( $post_id ) {
|
54 |
+
$data = $this->input->extract( $_POST );
|
55 |
+
|
56 |
+
if ( is_null( $data ) )
|
57 |
+
return;
|
58 |
+
|
59 |
+
$this->save( $post_id, $data );
|
60 |
+
}
|
61 |
+
|
62 |
+
function _box( $post ) {
|
63 |
+
$this->box( $post->ID );
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
|
68 |
+
class p2pInput {
|
69 |
+
|
70 |
+
private $prefix;
|
71 |
+
|
72 |
+
function __construct( $prefix = array() ) {
|
73 |
+
$this->prefix = $prefix;
|
74 |
+
}
|
75 |
+
|
76 |
+
function get_name( $suffix ) {
|
77 |
+
$name_a = array_merge( $this->prefix, (array) $suffix );
|
78 |
+
|
79 |
+
$name = array_shift( $name_a );
|
80 |
+
foreach ( $name_a as $key )
|
81 |
+
$name .= '[' . esc_attr( $key ) . ']';
|
82 |
+
|
83 |
+
return $name;
|
84 |
+
}
|
85 |
+
|
86 |
+
function extract( $value, $suffix = array() ) {
|
87 |
+
$name_a = array_merge( $this->prefix, (array) $suffix );
|
88 |
+
|
89 |
+
foreach ( $name_a as $key ) {
|
90 |
+
if ( !isset( $value[ $key ] ) )
|
91 |
+
return null;
|
92 |
+
|
93 |
+
$value = $value[$key];
|
94 |
+
}
|
95 |
+
|
96 |
+
return $value;
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
|
101 |
+
class P2P_Connection_Types {
|
102 |
+
|
103 |
+
private static $ctype_id = 0;
|
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 |
+
add_action( 'save_post', array( __CLASS__, '_save' ), 10 );
|
121 |
+
}
|
122 |
+
|
123 |
+
static function _register( $from ) {
|
124 |
+
foreach ( self::filter_ctypes( $from ) as $ctype ) {
|
125 |
+
$ctype->_register( $from );
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
static function _save( $post_id ) {
|
130 |
+
$from = get_post_type( $post_id );
|
131 |
+
if ( defined( 'DOING_AJAX' ) || defined( 'DOING_CRON' ) || empty( $_POST ) || 'revision' == $from )
|
132 |
+
return;
|
133 |
+
|
134 |
+
foreach ( self::filter_ctypes( $from ) as $ctype ) {
|
135 |
+
$ctype->_save( $post_id );
|
136 |
+
}
|
137 |
+
}
|
138 |
+
|
139 |
+
private static function filter_ctypes( $post_type ) {
|
140 |
+
$r = array();
|
141 |
+
$i = 0;
|
142 |
+
foreach ( self::$ctypes as $args ) {
|
143 |
+
if ( $post_type == $args['from'] ) {
|
144 |
+
$reversed = false;
|
145 |
+
} elseif ( $args['reciprocal'] && $post_type == $args['to'] ) {
|
146 |
+
$reversed = true;
|
147 |
+
} else {
|
148 |
+
continue;
|
149 |
+
}
|
150 |
+
|
151 |
+
$r[] = new $args['box']($args, $reversed, $i++);
|
152 |
+
}
|
153 |
+
|
154 |
+
return $r;
|
155 |
+
}
|
156 |
+
}
|
157 |
+
|