Posts 2 Posts - Version 1.2

Version Description

  • added Tools -> Connection Types admin screen
  • fixed migration script
  • made p2p_get_connections() accept arrays of ids
  • added 'separator' parameter to p2p_list_posts()
  • made P2P_Directed_Type->connect() return WP_Error instances instead of just false
  • when a user is deleted, delete all the associated connections
  • fixed conflict with bbPress Topics for Posts plugin
  • more info
Download this release

Release Info

Developer scribu
Plugin Icon wp plugin Posts 2 Posts
Version 1.2
Comparing to
See all releases

Code changes from version 1.1.6 to 1.2

admin/box-factory.php CHANGED
@@ -2,9 +2,6 @@
2
 
3
  define( 'P2P_BOX_NONCE', 'p2p-box' );
4
 
5
- /**
6
- * @package Administration
7
- */
8
  class P2P_Box_Factory {
9
 
10
  private static $box_args = array();
@@ -126,23 +123,17 @@ class P2P_Box_Factory {
126
  return;
127
 
128
  // Custom fields
129
- if ( isset( $_POST['p2p_types'] ) ) {
130
- foreach ( $_POST['p2p_types'] as $p2p_type ) {
131
- $ctype = p2p_type( $p2p_type );
132
- if ( !$ctype )
133
- continue;
134
-
135
- foreach ( $ctype->get_connections( $post_id ) as $p2p_id => $item_id ) {
136
- $fields = self::$box_args[$p2p_type]->fields;
137
 
138
- foreach ( $fields as $key => &$field ) {
139
- $field['name'] = $key;
140
- }
141
 
142
- $data = scbForms::get_value( array( 'p2p_meta', $p2p_id ), $_POST, array() );
143
-
144
- scbForms::update_meta( $fields, $data, $p2p_id, 'p2p' );
145
  }
 
 
146
  }
147
  }
148
 
2
 
3
  define( 'P2P_BOX_NONCE', 'p2p-box' );
4
 
 
 
 
5
  class P2P_Box_Factory {
6
 
7
  private static $box_args = array();
123
  return;
124
 
125
  // Custom fields
126
+ if ( isset( $_POST['p2p_meta'] ) ) {
127
+ foreach ( $_POST['p2p_meta'] as $p2p_id => $data ) {
128
+ $connection = p2p_get_connection( $p2p_id );
 
 
 
 
 
129
 
130
+ $fields = self::$box_args[$connection->p2p_type]->fields;
 
 
131
 
132
+ foreach ( $fields as $key => &$field ) {
133
+ $field['name'] = $key;
 
134
  }
135
+
136
+ scbForms::update_meta( $fields, $data, $p2p_id, 'p2p' );
137
  }
138
  }
139
 
admin/box.js CHANGED
@@ -33,7 +33,7 @@
33
  type == null && (type = 'POST');
34
  data.action = 'p2p_box';
35
  data.nonce = P2PAdmin.nonce;
36
- data.p2p_type = $metabox.find('input[name^="p2p_types"]').val();
37
  data.direction = $metabox.data('direction');
38
  data.from = jQuery('#post_ID').val();
39
  data.s = searchTab.params.s;
33
  type == null && (type = 'POST');
34
  data.action = 'p2p_box';
35
  data.nonce = P2PAdmin.nonce;
36
+ data.p2p_type = $metabox.data('p2p_type');
37
  data.direction = $metabox.data('direction');
38
  data.from = jQuery('#post_ID').val();
39
  data.s = searchTab.params.s;
admin/box.php CHANGED
@@ -1,16 +1,10 @@
1
  <?php
2
 
3
- /**
4
- * @package Administration
5
- */
6
  interface P2P_Field {
7
  function get_title();
8
  function render( $p2p_id, $post_id );
9
  }
10
 
11
- /**
12
- * @package Administration
13
- */
14
  class P2P_Box {
15
  private $ctype;
16
 
@@ -31,10 +25,10 @@ class P2P_Box {
31
  }
32
 
33
  public function init_scripts() {
34
- wp_enqueue_style( 'p2p-admin', plugins_url( 'box.css', __FILE__ ), array(), P2P_PLUGIN_VERSION );
35
 
36
- wp_enqueue_script( 'p2p-admin', plugins_url( 'box.js', __FILE__ ), array( 'jquery' ), P2P_PLUGIN_VERSION, true );
37
- wp_localize_script( 'p2p-admin', 'P2PAdmin', array(
38
  'nonce' => wp_create_nonce( P2P_BOX_NONCE ),
39
  'spinner' => admin_url( 'images/wpspin_light.gif' ),
40
  'deleteConfirmMessage' => __( 'Are you sure you want to delete all connections?', P2P_TEXTDOMAIN ),
@@ -65,10 +59,9 @@ class P2P_Box {
65
  }
66
 
67
  function render( $post ) {
68
- $this->connected_items = $this->ctype->get_connections( $post->ID );
69
 
70
  $data = array(
71
- 'p2p-type' => $this->ctype->name,
72
  'attributes' => $this->render_data_attributes(),
73
  'connections' => $this->render_connections_table( $post ),
74
  'create-connections' => $this->render_create_connections( $post ),
@@ -77,10 +70,19 @@ class P2P_Box {
77
  echo P2P_Mustache::render( 'box', $data );
78
  }
79
 
 
 
 
 
 
 
 
 
80
  protected function render_data_attributes() {
81
  $data_attr = array(
 
82
  'prevent_duplicates' => $this->ctype->prevent_duplicates,
83
- 'cardinality' => $this->ctype->accepts_single_connection() ? 'one' : 'many',
84
  'direction' => $this->ctype->get_direction()
85
  );
86
 
@@ -118,7 +120,7 @@ class P2P_Box {
118
  'label' => __( 'Create connections:', P2P_TEXTDOMAIN )
119
  );
120
 
121
- if ( $this->ctype->accepts_single_connection() && !empty( $this->connected_items ) )
122
  $data['hide'] = 'style="display:none"';
123
 
124
  // Search tab
1
  <?php
2
 
 
 
 
3
  interface P2P_Field {
4
  function get_title();
5
  function render( $p2p_id, $post_id );
6
  }
7
 
 
 
 
8
  class P2P_Box {
9
  private $ctype;
10
 
25
  }
26
 
27
  public function init_scripts() {
28
+ wp_enqueue_style( 'p2p-box', plugins_url( 'box.css', __FILE__ ), array(), P2P_PLUGIN_VERSION );
29
 
30
+ wp_enqueue_script( 'p2p-box', plugins_url( 'box.js', __FILE__ ), array( 'jquery' ), P2P_PLUGIN_VERSION, true );
31
+ wp_localize_script( 'p2p-box', 'P2PAdmin', array(
32
  'nonce' => wp_create_nonce( P2P_BOX_NONCE ),
33
  'spinner' => admin_url( 'images/wpspin_light.gif' ),
34
  'deleteConfirmMessage' => __( 'Are you sure you want to delete all connections?', P2P_TEXTDOMAIN ),
59
  }
60
 
61
  function render( $post ) {
62
+ $this->connected_items = $this->get_folded_connections( $post->ID );
63
 
64
  $data = array(
 
65
  'attributes' => $this->render_data_attributes(),
66
  'connections' => $this->render_connections_table( $post ),
67
  'create-connections' => $this->render_create_connections( $post ),
70
  echo P2P_Mustache::render( 'box', $data );
71
  }
72
 
73
+ protected function get_folded_connections( $post_id ) {
74
+ $side = $this->ctype->get_opposite( 'side' );
75
+
76
+ $query = $this->ctype->get_connected( $post_id, $side->get_connections_qv() );
77
+
78
+ return scb_list_fold( $side->abstract_query( $query )->items, 'p2p_id', 'ID' );
79
+ }
80
+
81
  protected function render_data_attributes() {
82
  $data_attr = array(
83
+ 'p2p_type' => $this->ctype->name,
84
  'prevent_duplicates' => $this->ctype->prevent_duplicates,
85
+ 'cardinality' => $this->ctype->get_opposite( 'cardinality' ),
86
  'direction' => $this->ctype->get_direction()
87
  );
88
 
120
  'label' => __( 'Create connections:', P2P_TEXTDOMAIN )
121
  );
122
 
123
+ if ( 'one' == $this->ctype->get_opposite( 'cardinality' ) && !empty( $this->connected_items ) )
124
  $data['hide'] = 'style="display:none"';
125
 
126
  // Search tab
admin/column-factory.php CHANGED
@@ -34,7 +34,7 @@ class P2P_Column_Factory {
34
  return true;
35
  }
36
 
37
- function add_columns() {
38
  $screen = get_current_screen();
39
 
40
  if ( 'edit' != $screen->base )
34
  return true;
35
  }
36
 
37
+ static function add_columns() {
38
  $screen = get_current_screen();
39
 
40
  if ( 'edit' != $screen->base )
admin/fields.php CHANGED
@@ -1,6 +1,5 @@
1
  <?php
2
 
3
- /** @package Administration */
4
  class P2P_Field_Create implements P2P_Field {
5
 
6
  function get_title() {
@@ -19,7 +18,6 @@ class P2P_Field_Create implements P2P_Field {
19
  }
20
 
21
 
22
- /** @package Administration */
23
  class P2P_Field_Delete implements P2P_Field {
24
 
25
  function get_title() {
@@ -41,7 +39,6 @@ class P2P_Field_Delete implements P2P_Field {
41
  }
42
 
43
 
44
- /** @package Administration */
45
  class P2P_Field_Order implements P2P_Field {
46
 
47
  protected $sort_key;
@@ -63,7 +60,6 @@ class P2P_Field_Order implements P2P_Field {
63
  }
64
  }
65
 
66
- /** @package Administration */
67
  class P2P_Field_Generic implements P2P_Field {
68
 
69
  protected $key;
@@ -87,12 +83,14 @@ class P2P_Field_Generic implements P2P_Field {
87
  if ( isset( $this->data['values'] ) )
88
  $args['value'] = $this->data['values'];
89
 
 
 
 
90
  return scbForms::input_from_meta( $args, $p2p_id, 'p2p' );
91
  }
92
  }
93
 
94
 
95
- /** @package Administration */
96
  class P2P_Field_Title_Post implements P2P_Field {
97
 
98
  protected $title;
@@ -126,7 +124,6 @@ class P2P_Field_Title_Post implements P2P_Field {
126
  }
127
 
128
 
129
- /** @package Administration */
130
  class P2P_Field_Title_Attachment extends P2P_Field_Title_Post {
131
 
132
  function render( $p2p_id, $attachment_id ) {
@@ -143,7 +140,6 @@ class P2P_Field_Title_Attachment extends P2P_Field_Title_Post {
143
  }
144
 
145
 
146
- /** @package Administration */
147
  class P2P_Field_Title_User extends P2P_Field_Title_Post {
148
 
149
  function render( $p2p_id, $user_id ) {
1
  <?php
2
 
 
3
  class P2P_Field_Create implements P2P_Field {
4
 
5
  function get_title() {
18
  }
19
 
20
 
 
21
  class P2P_Field_Delete implements P2P_Field {
22
 
23
  function get_title() {
39
  }
40
 
41
 
 
42
  class P2P_Field_Order implements P2P_Field {
43
 
44
  protected $sort_key;
60
  }
61
  }
62
 
 
63
  class P2P_Field_Generic implements P2P_Field {
64
 
65
  protected $key;
83
  if ( isset( $this->data['values'] ) )
84
  $args['value'] = $this->data['values'];
85
 
86
+ if ( 'select' == $args['type'] )
87
+ $args['text'] = '';
88
+
89
  return scbForms::input_from_meta( $args, $p2p_id, 'p2p' );
90
  }
91
  }
92
 
93
 
 
94
  class P2P_Field_Title_Post implements P2P_Field {
95
 
96
  protected $title;
124
  }
125
 
126
 
 
127
  class P2P_Field_Title_Attachment extends P2P_Field_Title_Post {
128
 
129
  function render( $p2p_id, $attachment_id ) {
140
  }
141
 
142
 
 
143
  class P2P_Field_Title_User extends P2P_Field_Title_Post {
144
 
145
  function render( $p2p_id, $user_id ) {
admin/{utils.php → mustache.php} RENAMED
File without changes
admin/templates/box.html CHANGED
@@ -1,6 +1,4 @@
1
  <div class="p2p-box" {{attributes}}>
2
- <input type="hidden" name="p2p_types[]" value="{{p2p-type}}" />
3
-
4
  {{#connections}}
5
  <table class="p2p-connections" {{{hide}}}>
6
  <thead>
1
  <div class="p2p-box" {{attributes}}>
 
 
2
  {{#connections}}
3
  <table class="p2p-connections" {{{hide}}}>
4
  <thead>
admin/templates/connection-types-form.html ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <input type="hidden" name="old_p2p_type" value="{{old_p2p_type}}" />
2
+ <select name="new_p2p_type">
3
+ <option></option>
4
+ {{#options}}
5
+ <option>{{.}}</option>
6
+ {{/options}}
7
+ </select>
8
+ <input class="button" type="submit" name="p2p_convert" value="{{{button_text}}}" />
admin/templates/connection-types.html ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <table class="widefat">
2
+ <thead>
3
+ <tr>
4
+ {{#columns}}
5
+ <th>{{.}}</th>
6
+ {{/columns}}
7
+ </tr>
8
+ </thead>
9
+ <tbody>
10
+ {{#rows}}
11
+ <tr class="{{class}}">
12
+ <td>{{p2p_type}}</td>
13
+ <td>{{{desc}}}</td>
14
+ <td>{{count}}</td>
15
+ </tr>
16
+ {{/rows}}
17
+ </tbody>
18
+ </table>
admin/tools.css ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .widefat {
2
+ margin-top: 15px;
3
+ }
4
+
5
+ .widefat .error {
6
+ background-color: pink;
7
+ }
8
+
9
+ .widefat td form {
10
+ display: inline;
11
+ }
12
+
13
+ .widefat td {
14
+ vertical-align: middle;
15
+ }
admin/tools.php ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class P2P_Tools_Page extends scbAdminPage {
4
+
5
+ function setup() {
6
+ $this->args = array(
7
+ 'page_title' => __( 'Connection Types', P2P_TEXTDOMAIN ),
8
+ 'page_slug' => 'connection-types',
9
+ 'parent' => 'tools.php'
10
+ );
11
+
12
+ add_action( 'admin_notices', array( $this, 'maybe_install' ) );
13
+ }
14
+
15
+ function maybe_install() {
16
+ if ( !current_user_can( 'manage_options' ) )
17
+ return;
18
+
19
+ $current_ver = get_option( 'p2p_storage' );
20
+
21
+ if ( $current_ver == P2P_Storage::$version )
22
+ return;
23
+
24
+ P2P_Storage::install();
25
+
26
+ if ( isset( $_GET['p2p-upgrade'] ) ) {
27
+ $n = P2P_Storage::upgrade();
28
+
29
+ update_option( 'p2p_storage', P2P_Storage::$version );
30
+
31
+ echo scb_admin_notice( sprintf( __( 'Upgraded %d connections.', P2P_TEXTDOMAIN ), $n ) );
32
+ } elseif ( $current_ver ) {
33
+ echo scb_admin_notice( sprintf(
34
+ __( 'The Posts 2 Posts connections need to be upgraded. <a href="%s">Proceed.</a>', P2P_TEXTDOMAIN ),
35
+ admin_url( 'tools.php?page=connection-types&p2p-upgrade=1' )
36
+ ) );
37
+ } else {
38
+ update_option( 'p2p_storage', P2P_Storage::$version );
39
+ }
40
+ }
41
+
42
+ function form_handler() {
43
+ if ( empty( $_POST['p2p_convert'] ) )
44
+ return false;
45
+
46
+ check_admin_referer( $this->nonce );
47
+
48
+ global $wpdb;
49
+
50
+ $old_p2p_type = $_POST['old_p2p_type'];
51
+ $new_p2p_type = $_POST['new_p2p_type'];
52
+
53
+ if ( !p2p_type( $new_p2p_type ) ) {
54
+ $this->admin_msg( sprintf( __( '<em>%s</em> is not a registered connection type.', P2P_TEXTDOMAIN ), esc_html( $new_p2p_type ) ) );
55
+ return;
56
+ }
57
+
58
+ $count = $wpdb->update( $wpdb->p2p,
59
+ array( 'p2p_type' => $new_p2p_type ),
60
+ array( 'p2p_type' => $old_p2p_type )
61
+ );
62
+
63
+ $this->admin_msg( sprintf( __( 'Converted %1$s connections from <em>%2$s</em> to <em>%3$s</em>.' ),
64
+ number_format_i18n( $count ),
65
+ esc_html( $old_p2p_type ),
66
+ esc_html( $new_p2p_type )
67
+ ) );
68
+ }
69
+
70
+ function page_head() {
71
+ wp_enqueue_style( 'p2p-tools', plugins_url( 'tools.css', __FILE__ ), array(), P2P_PLUGIN_VERSION );
72
+ }
73
+
74
+ function page_content() {
75
+ $data = array(
76
+ 'columns' => array(
77
+ __( 'Name', P2P_TEXTDOMAIN ),
78
+ __( 'Information', P2P_TEXTDOMAIN ),
79
+ __( 'Connections', P2P_TEXTDOMAIN ),
80
+ )
81
+ );
82
+
83
+ foreach ( $this->get_connection_counts() as $p2p_type => $count ) {
84
+ $row = array(
85
+ 'p2p_type' => $p2p_type,
86
+ 'count' => number_format_i18n( $count )
87
+ );
88
+
89
+ $ctype = p2p_type( $p2p_type );
90
+
91
+ if ( $ctype ) {
92
+ $row['desc'] = $ctype->get_desc();
93
+ } else {
94
+ $row['desc'] = __( 'Convert to registered connection type:', P2P_TEXTDOMAIN ) . scbForms::form_wrap( $this->get_dropdown( $p2p_type ), $this->nonce );
95
+ $row['class'] = 'error';
96
+ }
97
+
98
+ $data['rows'][] = $row;
99
+ }
100
+
101
+ echo P2P_Mustache::render( 'connection-types', $data );
102
+ }
103
+
104
+ private function get_connection_counts() {
105
+ global $wpdb;
106
+
107
+ $counts = $wpdb->get_results( "
108
+ SELECT p2p_type, COUNT(*) as count
109
+ FROM $wpdb->p2p
110
+ GROUP BY p2p_type
111
+ " );
112
+
113
+ $counts = scb_list_fold( $counts, 'p2p_type', 'count' );
114
+
115
+ foreach ( P2P_Connection_Type_Factory::get_all_instances() as $p2p_type => $ctype ) {
116
+ if ( !isset( $counts[ $p2p_type ] ) )
117
+ $counts[ $p2p_type ] = 0;
118
+ }
119
+
120
+ ksort( $counts );
121
+
122
+ return $counts;
123
+ }
124
+
125
+ private function get_dropdown( $p2p_type ) {
126
+ $data = array(
127
+ 'old_p2p_type' => $p2p_type,
128
+ 'options' => array_keys( P2P_Connection_Type_Factory::get_all_instances() ),
129
+ 'button_text' => __( 'Go', P2P_TEXTDOMAIN )
130
+ );
131
+
132
+ return P2P_Mustache::render( 'connection-types-form', $data );
133
+ }
134
+ }
135
+
136
+ new P2P_Tools_Page;
137
+
core/api.php CHANGED
@@ -164,7 +164,12 @@ function _p2p_get_connections( $p2p_type, $args = array() ) {
164
  if ( 'any' == $$key )
165
  continue;
166
 
167
- $where .= $wpdb->prepare( " AND p2p_$key = %d", $$key );
 
 
 
 
 
168
  }
169
 
170
  switch ( $fields ) {
@@ -311,6 +316,7 @@ function p2p_list_posts( $posts, $args = array() ) {
311
  $args = wp_parse_args( $args, array(
312
  'before_list' => '<ul>', 'after_list' => '</ul>',
313
  'before_item' => '<li>', 'after_item' => '</li>',
 
314
  'template' => false
315
  ) );
316
 
@@ -321,19 +327,25 @@ function p2p_list_posts( $posts, $args = array() ) {
321
 
322
  echo $before_list;
323
 
 
 
324
  foreach ( $posts as $post ) {
325
  $GLOBALS['post'] = $post;
326
 
327
  setup_postdata( $post );
328
 
329
- echo $before_item;
330
 
331
  if ( $template )
332
  locate_template( $template, true, false );
333
  else
334
- echo html( 'a', array( 'href' => get_permalink( $post->ID ) ), get_the_title( $post->ID ) );
 
 
 
 
335
 
336
- echo $after_item;
337
  }
338
 
339
  echo $after_list;
164
  if ( 'any' == $$key )
165
  continue;
166
 
167
+ if ( empty( $$key ) )
168
+ return array();
169
+
170
+ $value = scbUtil::array_to_sql( (array) $$key );
171
+
172
+ $where .= " AND p2p_$key IN ($value)";
173
  }
174
 
175
  switch ( $fields ) {
316
  $args = wp_parse_args( $args, array(
317
  'before_list' => '<ul>', 'after_list' => '</ul>',
318
  'before_item' => '<li>', 'after_item' => '</li>',
319
+ 'separator' => false,
320
  'template' => false
321
  ) );
322
 
327
 
328
  echo $before_list;
329
 
330
+ $i = 0;
331
+
332
  foreach ( $posts as $post ) {
333
  $GLOBALS['post'] = $post;
334
 
335
  setup_postdata( $post );
336
 
337
+ if ( !$separator ) echo $before_item;
338
 
339
  if ( $template )
340
  locate_template( $template, true, false );
341
  else
342
+ if ( 0 < $i && $separator ) echo $separator;
343
+
344
+ echo html( 'a', array( 'href' => get_permalink() ), get_the_title() );
345
+
346
+ if ( !$separator ) echo $after_item;
347
 
348
+ $i++;
349
  }
350
 
351
  echo $after_list;
core/directed-type.php CHANGED
@@ -48,10 +48,6 @@ class P2P_Directed_Connection_Type {
48
  return $arg[$direction];
49
  }
50
 
51
- public function accepts_single_connection() {
52
- return 'one' == $this->get_opposite( 'cardinality' );
53
- }
54
-
55
  /**
56
  * Get a list of posts that are connected to a given post.
57
  *
@@ -109,48 +105,41 @@ class P2P_Directed_Connection_Type {
109
  return false;
110
  }
111
 
112
- /** @internal */
113
- public function get_connections( $post_id ) {
114
- $side = $this->get_opposite( 'side' );
115
-
116
- $query = $this->get_connected( $post_id, $side->get_connections_qv() );
117
-
118
- return scb_list_fold( $side->abstract_query( $query )->items, 'p2p_id', 'ID' );
119
- }
120
-
121
  /**
122
  * Get a list of posts that could be connected to a given post.
123
  *
124
  * @param int $post_id A post id.
125
  */
126
  public function get_connectable( $item_id, $page, $search ) {
 
 
 
 
 
 
 
 
 
 
127
  $to_exclude = array();
128
 
129
  if ( $this->indeterminate && !$this->self_connections )
130
  $to_exclude[] = $item_id;
131
 
132
  if ( 'one' == $this->get_current( 'cardinality' ) ) {
133
- _p2p_append( $to_exclude, p2p_get_connections( $this->name, array(
134
- 'direction' => $this->direction,
135
  'fields' => 'object_id'
136
  ) ) );
137
  }
138
 
139
  if ( $this->prevent_duplicates ) {
140
- _p2p_append( $to_exclude, p2p_get_connections( $this->name, array(
141
- 'direction' => $this->direction,
142
  'from' => $item_id,
143
  'fields' => 'object_id'
144
  ) ) );
145
  }
146
 
147
- $side = $this->get_opposite( 'side' );
148
-
149
- $qv = $side->get_connectable_qv( $item_id, $page, $search, $to_exclude );
150
-
151
- $qv = apply_filters( 'p2p_connectable_args', $qv, $this, $item_id );
152
-
153
- return $side->abstract_query( $side->do_query( $qv ) );
154
  }
155
 
156
  /**
@@ -160,31 +149,28 @@ class P2P_Directed_Connection_Type {
160
  * @param int The second end of the connection.
161
  * @param array Additional information about the connection.
162
  *
163
- * @return int p2p_id
164
  */
165
  public function connect( $from, $to, $meta = array() ) {
166
  if ( !$this->get_current( 'side' )->item_exists( $from ) )
167
- return false;
168
 
169
  if ( !$this->get_opposite( 'side' )->item_exists( $to ) )
170
- return false;
171
 
172
- if ( $this->accepts_single_connection() )
173
- $to_check = 'any';
174
- elseif ( $this->prevent_duplicates )
175
- $to_check = $to;
176
- else
177
- $to_check = false;
178
 
179
- if ( $to_check && p2p_connection_exists( $this->name, array(
180
- 'direction' => $this->direction,
181
- 'from' => $from,
182
- 'to' => $to_check
183
- ) ) )
184
- return false;
185
 
186
- return p2p_create_connection( $this->name, array(
187
- 'direction' => $this->direction,
 
 
 
 
 
188
  'from' => $from,
189
  'to' => $to,
190
  'meta' => array_merge( $meta, $this->data )
@@ -198,11 +184,7 @@ class P2P_Directed_Connection_Type {
198
  * @param int The second end of the connection.
199
  */
200
  public function disconnect( $from, $to ) {
201
- return p2p_delete_connections( $this->name, array(
202
- 'direction' => $this->direction,
203
- 'from' => $from,
204
- 'to' => $to,
205
- ) );
206
  }
207
 
208
  /**
@@ -211,47 +193,24 @@ class P2P_Directed_Connection_Type {
211
  * @param int The post id.
212
  */
213
  public function disconnect_all( $from ) {
214
- return p2p_delete_connections( $this->name, array(
215
- 'direction' => $this->direction,
216
- 'from' => $from,
217
- ) );
218
- }
219
-
220
- /**
221
- * For one-to-many connections: replaces existing item with a new one.
222
- *
223
- * @param int The first end of the connection.
224
- * @param int The second end of the connection.
225
- * @param array Additional information about the connection.
226
- *
227
- * @return int p2p_id
228
- */
229
- public function replace( $from, $to, $meta = array() ) {
230
- if ( !$this->get_current( 'side' )->item_exists( $from ) )
231
- return false;
232
-
233
- if ( ! $this->accepts_single_connection() )
234
- return false;
235
-
236
- $existing = _p2p_first( $this->get_connections( $from ) );
237
-
238
- if ( $existing ) {
239
- if ( $existing == $to )
240
- return;
241
-
242
- $this->disconnect_all( $from );
243
- }
244
-
245
- return $this->connect( $from, $to, $meta );
246
  }
247
 
248
  public function get_p2p_id( $from, $to ) {
249
- return _p2p_first( p2p_get_connections( $this->name, array(
250
- 'direction' => $this->direction,
251
  'from' => $from,
252
  'to' => $to,
253
  'fields' => 'p2p_id'
254
  ) ) );
255
  }
 
 
 
 
 
 
 
 
 
256
  }
257
 
48
  return $arg[$direction];
49
  }
50
 
 
 
 
 
51
  /**
52
  * Get a list of posts that are connected to a given post.
53
  *
105
  return false;
106
  }
107
 
 
 
 
 
 
 
 
 
 
108
  /**
109
  * Get a list of posts that could be connected to a given post.
110
  *
111
  * @param int $post_id A post id.
112
  */
113
  public function get_connectable( $item_id, $page, $search ) {
114
+ $side = $this->get_opposite( 'side' );
115
+
116
+ $qv = $side->get_connectable_qv( $item_id, $page, $search, $this->get_non_connectable( $item_id ) );
117
+
118
+ $qv = apply_filters( 'p2p_connectable_args', $qv, $this, $item_id );
119
+
120
+ return $side->abstract_query( $side->do_query( $qv ) );
121
+ }
122
+
123
+ private function get_non_connectable( $item_id ) {
124
  $to_exclude = array();
125
 
126
  if ( $this->indeterminate && !$this->self_connections )
127
  $to_exclude[] = $item_id;
128
 
129
  if ( 'one' == $this->get_current( 'cardinality' ) ) {
130
+ _p2p_append( $to_exclude, $this->get_connections( array(
 
131
  'fields' => 'object_id'
132
  ) ) );
133
  }
134
 
135
  if ( $this->prevent_duplicates ) {
136
+ _p2p_append( $to_exclude, $this->get_connections( array(
 
137
  'from' => $item_id,
138
  'fields' => 'object_id'
139
  ) ) );
140
  }
141
 
142
+ return $to_exclude;
 
 
 
 
 
 
143
  }
144
 
145
  /**
149
  * @param int The second end of the connection.
150
  * @param array Additional information about the connection.
151
  *
152
+ * @return int|object p2p_id or WP_Error on failure
153
  */
154
  public function connect( $from, $to, $meta = array() ) {
155
  if ( !$this->get_current( 'side' )->item_exists( $from ) )
156
+ return new WP_Error( 'first_parameter', 'Invalid first parameter.' );
157
 
158
  if ( !$this->get_opposite( 'side' )->item_exists( $to ) )
159
+ return new WP_Error( 'second_parameter', 'Invalid second parameter.' );
160
 
161
+ if ( !$this->self_connections && $from == $to )
162
+ return new WP_Error( 'self_connection', 'Connection between an element and itself is not allowed.' );
 
 
 
 
163
 
164
+ if ( $this->prevent_duplicates && $this->get_p2p_id( $from, $to ) )
165
+ return new WP_Error( 'duplicate_connection', 'Duplicate connections are not allowed.' );
 
 
 
 
166
 
167
+ if ( 'one' == $this->get_opposite( 'cardinality' ) && $this->connection_exists( compact( 'from' ) ) )
168
+ return new WP_Error( 'cardinality_opposite', 'Cardinality problem.' );
169
+
170
+ if ( 'one' == $this->get_current( 'cardinality' ) && $this->connection_exists( compact( 'to' ) ) )
171
+ return new WP_Error( 'cardinality_current', 'Cardinality problem.' );
172
+
173
+ return $this->create_connection( array(
174
  'from' => $from,
175
  'to' => $to,
176
  'meta' => array_merge( $meta, $this->data )
184
  * @param int The second end of the connection.
185
  */
186
  public function disconnect( $from, $to ) {
187
+ return $this->delete_connections( compact( 'from', 'to' ) );
 
 
 
 
188
  }
189
 
190
  /**
193
  * @param int The post id.
194
  */
195
  public function disconnect_all( $from ) {
196
+ return $this->delete_connections( compact( 'from' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  }
198
 
199
  public function get_p2p_id( $from, $to ) {
200
+ return _p2p_first( $this->get_connections( array(
 
201
  'from' => $from,
202
  'to' => $to,
203
  'fields' => 'p2p_id'
204
  ) ) );
205
  }
206
+
207
+ /**
208
+ * Transforms $this->get_connections( ... ) into p2p_get_connections( $this->name, ... ) etc.
209
+ */
210
+ public function __call( $method, $args ) {
211
+ $args[0]['direction'] = $this->direction;
212
+
213
+ return call_user_func( 'p2p_' . $method, $this->name, $args[0] );
214
+ }
215
  }
216
 
core/query-post.php CHANGED
@@ -5,27 +5,21 @@
5
  */
6
  class P2P_WP_Query {
7
 
8
- function init() {
9
- add_action( 'parse_query', array( __CLASS__, 'parse_query' ) );
10
  add_filter( 'posts_clauses', array( __CLASS__, 'posts_clauses' ), 10, 2 );
11
- add_filter( 'the_posts', array( __CLASS__, 'cache_p2p_meta' ), 11, 2 );
12
  }
13
 
14
- function parse_query( $wp_query ) {
15
  $q =& $wp_query->query_vars;
16
 
17
  P2P_Query::expand_shortcut_qv( $q );
18
 
19
- if ( !isset( $q['connected_items'] ) )
20
- return;
21
-
22
- if ( !isset( $q['connected_type'] ) )
23
- return;
24
-
25
- if ( 'any' == $q['connected_items'] ) {
26
- $item = isset( $q['post_type'] ) ? $q['post_type'] : 'post';
27
- } else {
28
  $item = $q['connected_items'];
 
 
29
  }
30
 
31
  $r = P2P_Query::expand_connected_type( $q, $item, 'post' );
@@ -38,12 +32,12 @@ class P2P_WP_Query {
38
  }
39
  }
40
 
41
- function posts_clauses( $clauses, $wp_query ) {
42
  global $wpdb;
43
 
44
  $qv = P2P_Query::get_qv( $wp_query->query_vars );
45
 
46
- if ( empty( $qv['items'] ) )
47
  return $clauses;
48
 
49
  $wp_query->_p2p_cache = true;
@@ -54,7 +48,7 @@ class P2P_WP_Query {
54
  /**
55
  * Pre-populates the p2p meta cache to decrease the number of queries.
56
  */
57
- function cache_p2p_meta( $the_posts, $wp_query ) {
58
  if ( empty( $the_posts ) )
59
  return $the_posts;
60
 
5
  */
6
  class P2P_WP_Query {
7
 
8
+ static function init() {
9
+ add_action( 'parse_query', array( __CLASS__, 'parse_query' ), 20 );
10
  add_filter( 'posts_clauses', array( __CLASS__, 'posts_clauses' ), 10, 2 );
11
+ add_filter( 'the_posts', array( __CLASS__, 'cache_p2p_meta' ), 20, 2 );
12
  }
13
 
14
+ static function parse_query( $wp_query ) {
15
  $q =& $wp_query->query_vars;
16
 
17
  P2P_Query::expand_shortcut_qv( $q );
18
 
19
+ if ( isset( $q['connected_items'] ) ) {
 
 
 
 
 
 
 
 
20
  $item = $q['connected_items'];
21
+ } else {
22
+ $item = isset( $q['post_type'] ) ? $q['post_type'] : 'post';
23
  }
24
 
25
  $r = P2P_Query::expand_connected_type( $q, $item, 'post' );
32
  }
33
  }
34
 
35
+ static function posts_clauses( $clauses, $wp_query ) {
36
  global $wpdb;
37
 
38
  $qv = P2P_Query::get_qv( $wp_query->query_vars );
39
 
40
+ if ( !$qv )
41
  return $clauses;
42
 
43
  $wp_query->_p2p_cache = true;
48
  /**
49
  * Pre-populates the p2p meta cache to decrease the number of queries.
50
  */
51
+ static function cache_p2p_meta( $the_posts, $wp_query ) {
52
  if ( empty( $the_posts ) )
53
  return $the_posts;
54
 
core/query-user.php CHANGED
@@ -2,21 +2,24 @@
2
 
3
  class P2P_User_Query {
4
 
5
- function init() {
6
- add_action( 'pre_user_query', array( __CLASS__, 'pre_user_query' ) );
7
  }
8
 
9
- function pre_user_query( $query ) {
10
  global $wpdb;
11
 
12
  $q =& $query->query_vars;
13
 
14
  P2P_Query::expand_shortcut_qv( $q );
15
 
16
- if ( !isset( $q['connected_items'] ) )
17
- return;
 
 
 
18
 
19
- $r = P2P_Query::expand_connected_type( $q, $q['connected_items'], 'user' );
20
 
21
  if ( false === $r ) {
22
  $query->query_where = " AND 1=0";
@@ -27,7 +30,7 @@ class P2P_User_Query {
27
 
28
  $qv = P2P_Query::get_qv( $q );
29
 
30
- if ( empty( $qv['items'] ) )
31
  return;
32
 
33
  $map = array(
2
 
3
  class P2P_User_Query {
4
 
5
+ static function init() {
6
+ add_action( 'pre_user_query', array( __CLASS__, 'pre_user_query' ), 20 );
7
  }
8
 
9
+ static function pre_user_query( $query ) {
10
  global $wpdb;
11
 
12
  $q =& $query->query_vars;
13
 
14
  P2P_Query::expand_shortcut_qv( $q );
15
 
16
+ if ( isset( $q['connected_items'] ) ) {
17
+ $item = $q['connected_items'];
18
+ } else {
19
+ $item = 'any';
20
+ }
21
 
22
+ $r = P2P_Query::expand_connected_type( $q, $item, 'user' );
23
 
24
  if ( false === $r ) {
25
  $query->query_where = " AND 1=0";
30
 
31
  $qv = P2P_Query::get_qv( $q );
32
 
33
+ if ( !$qv )
34
  return;
35
 
36
  $map = array(
core/query.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  class P2P_Query {
4
 
5
- function expand_shortcut_qv( &$q ) {
6
  $qv_map = array(
7
  'connected' => 'any',
8
  'connected_to' => 'to',
@@ -17,7 +17,16 @@ class P2P_Query {
17
  }
18
  }
19
 
20
- function get_qv( $q ) {
 
 
 
 
 
 
 
 
 
21
  $qv_list = array(
22
  'items', 'direction', 'meta',
23
  'orderby', 'order_num', 'order'
@@ -27,15 +36,18 @@ class P2P_Query {
27
  $qv[$key] = isset( $q["connected_$key"] ) ? $q["connected_$key"] : false;
28
  }
29
 
30
- $qv['p2p_type'] = isset( $q['p2p_type'] ) ? $q['p2p_type'] : false;
31
-
32
  return $qv;
33
  }
34
 
35
- // null means do nothing
36
- // false means trigger 404
37
- // true means found valid p2p query vars
38
- function expand_connected_type( &$q, $item, $object_type ) {
 
 
 
 
 
39
  if ( !isset( $q['connected_type'] ) )
40
  return;
41
 
@@ -60,14 +72,15 @@ class P2P_Query {
60
  $directed = self::find_direction( $ctype, $item, $object_type );
61
  }
62
 
63
- if ( !$directed ) {
64
- trigger_error( "Can't determine direction", E_USER_WARNING );
65
  continue;
66
- }
67
 
68
  $p2p_types[ $p2p_type ] = $directed->get_direction();
69
  }
70
 
 
 
 
71
  if ( 1 == count( $p2p_types ) )
72
  $q = $directed->get_connected_args( $q );
73
  else
@@ -76,7 +89,7 @@ class P2P_Query {
76
  return true;
77
  }
78
 
79
- function alter_clauses( $clauses, $q, $main_id_column ) {
80
  global $wpdb;
81
 
82
  $clauses['fields'] .= ", $wpdb->p2p.*";
@@ -93,7 +106,7 @@ class P2P_Query {
93
  $where_parts = array();
94
 
95
  foreach ( $q['p2p_type'] as $p2p_type => $direction ) {
96
- if ( false === $p2p_type ) // used by migration script
97
  $part = "1 = 1";
98
  else
99
  $part = $wpdb->prepare( "$wpdb->p2p.p2p_type = %s", $p2p_type );
2
 
3
  class P2P_Query {
4
 
5
+ static function expand_shortcut_qv( &$q ) {
6
  $qv_map = array(
7
  'connected' => 'any',
8
  'connected_to' => 'to',
17
  }
18
  }
19
 
20
+ static function get_qv( $q ) {
21
+ if ( !isset( $q['p2p_type'] ) ) {
22
+ if ( isset( $q['connected_items'] ) ) {
23
+ trigger_error( "P2P queries without 'connected_type' are no longer supported." );
24
+ }
25
+ return false;
26
+ }
27
+
28
+ $qv['p2p_type'] = $q['p2p_type'];
29
+
30
  $qv_list = array(
31
  'items', 'direction', 'meta',
32
  'orderby', 'order_num', 'order'
36
  $qv[$key] = isset( $q["connected_$key"] ) ? $q["connected_$key"] : false;
37
  }
38
 
 
 
39
  return $qv;
40
  }
41
 
42
+ /**
43
+ * Sets 'p2p_type' => array( connection_type => direction )
44
+ *
45
+ * @return:
46
+ * null means ignore current query
47
+ * false means trigger 404
48
+ * true means proceed
49
+ */
50
+ static function expand_connected_type( &$q, $item, $object_type ) {
51
  if ( !isset( $q['connected_type'] ) )
52
  return;
53
 
72
  $directed = self::find_direction( $ctype, $item, $object_type );
73
  }
74
 
75
+ if ( !$directed )
 
76
  continue;
 
77
 
78
  $p2p_types[ $p2p_type ] = $directed->get_direction();
79
  }
80
 
81
+ if ( empty( $p2p_types ) )
82
+ return false;
83
+
84
  if ( 1 == count( $p2p_types ) )
85
  $q = $directed->get_connected_args( $q );
86
  else
89
  return true;
90
  }
91
 
92
+ static function alter_clauses( $clauses, $q, $main_id_column ) {
93
  global $wpdb;
94
 
95
  $clauses['fields'] .= ", $wpdb->p2p.*";
106
  $where_parts = array();
107
 
108
  foreach ( $q['p2p_type'] as $p2p_type => $direction ) {
109
+ if ( 0 === $p2p_type ) // used by migration script
110
  $part = "1 = 1";
111
  else
112
  $part = $wpdb->prepare( "$wpdb->p2p.p2p_type = %s", $p2p_type );
core/side.php CHANGED
@@ -34,6 +34,15 @@ class P2P_Side_Post extends P2P_Side {
34
  ) );
35
  }
36
 
 
 
 
 
 
 
 
 
 
37
  function get_title() {
38
  return $this->get_ptype()->labels->name;
39
  }
@@ -136,10 +145,14 @@ class P2P_Side_Attachment extends P2P_Side_Post {
136
 
137
  class P2P_Side_User extends P2P_Side {
138
 
139
- function get_title() {
140
  return __( 'Users', P2P_TEXTDOMAIN );
141
  }
142
 
 
 
 
 
143
  function get_labels() {
144
  return (object) array(
145
  'singular_name' => __( 'User', P2P_TEXTDOMAIN ),
34
  ) );
35
  }
36
 
37
+ function get_desc() {
38
+ return implode( ', ', array_map( array( $this, 'post_type_label' ), $this->post_type ) );
39
+ }
40
+
41
+ private function post_type_label( $post_type ) {
42
+ $cpt = get_post_type_object( $post_type );
43
+ return $cpt ? $cpt->label : $post_type;
44
+ }
45
+
46
  function get_title() {
47
  return $this->get_ptype()->labels->name;
48
  }
145
 
146
  class P2P_Side_User extends P2P_Side {
147
 
148
+ function get_desc() {
149
  return __( 'Users', P2P_TEXTDOMAIN );
150
  }
151
 
152
+ function get_title() {
153
+ return $this->get_desc();
154
+ }
155
+
156
  function get_labels() {
157
  return (object) array(
158
  'singular_name' => __( 'User', P2P_TEXTDOMAIN ),
core/storage.php CHANGED
@@ -7,43 +7,15 @@ class P2P_Storage {
7
 
8
  static $version = 4;
9
 
10
- function init() {
11
  scb_register_table( 'p2p' );
12
  scb_register_table( 'p2pmeta' );
13
 
14
- add_action( 'admin_notices', array( __CLASS__, 'maybe_install' ) );
15
-
16
- add_action( 'deleted_post', array( __CLASS__, 'deleted_post' ) );
17
- }
18
-
19
- function maybe_install() {
20
- if ( !current_user_can( 'manage_options' ) )
21
- return;
22
-
23
- $current_ver = get_option( 'p2p_storage' );
24
-
25
- if ( $current_ver == self::$version )
26
- return;
27
-
28
- self::install();
29
-
30
- if ( isset( $_GET['p2p-upgrade'] ) ) {
31
- $n = self::upgrade();
32
-
33
- update_option( 'p2p_storage', P2P_Storage::$version );
34
-
35
- echo scb_admin_notice( sprintf( __( 'Upgraded %d connections.', P2P_TEXTDOMAIN ), $n ) );
36
- } elseif ( $current_ver ) {
37
- echo scb_admin_notice( sprintf(
38
- __( 'The Posts 2 Posts connections need to be upgraded. <a href="%s">Proceed.</a>', P2P_TEXTDOMAIN ),
39
- admin_url( 'tools.php?p2p-upgrade' )
40
- ) );
41
- } else {
42
- update_option( 'p2p_storage', P2P_Storage::$version );
43
- }
44
  }
45
 
46
- function install() {
47
  scb_install_table( 'p2p', "
48
  p2p_id bigint(20) unsigned NOT NULL auto_increment,
49
  p2p_from bigint(20) unsigned NOT NULL,
@@ -66,7 +38,7 @@ class P2P_Storage {
66
  " );
67
  }
68
 
69
- function upgrade() {
70
  global $wpdb;
71
 
72
  $n = 0;
@@ -82,7 +54,7 @@ class P2P_Storage {
82
  'nopaging' => true
83
  ) );
84
 
85
- $args['p2p_type'] = array( false => $args['direction'] );
86
 
87
  foreach ( get_posts( $args ) as $post ) {
88
  // some connections might be ambiguous, spanning multiple connection types; first one wins
@@ -96,19 +68,21 @@ class P2P_Storage {
96
  return $n;
97
  }
98
 
99
- function uninstall() {
100
  scb_uninstall_table( 'p2p' );
101
  scb_uninstall_table( 'p2pmeta' );
102
 
103
  delete_option( 'p2p_storage' );
104
  }
105
 
106
- function deleted_post( $post_id ) {
 
 
107
  foreach ( P2P_Connection_Type_Factory::get_all_instances() as $p2p_type => $ctype ) {
108
  foreach ( array( 'from', 'to' ) as $direction ) {
109
- if ( 'post' == $ctype->object[ $direction ] ) {
110
  p2p_delete_connections( $p2p_type, array(
111
- $direction => $post_id,
112
  ) );
113
  }
114
  }
7
 
8
  static $version = 4;
9
 
10
+ static function init() {
11
  scb_register_table( 'p2p' );
12
  scb_register_table( 'p2pmeta' );
13
 
14
+ add_action( 'deleted_post', array( __CLASS__, 'deleted_object' ) );
15
+ add_action( 'deleted_user', array( __CLASS__, 'deleted_object' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  }
17
 
18
+ static function install() {
19
  scb_install_table( 'p2p', "
20
  p2p_id bigint(20) unsigned NOT NULL auto_increment,
21
  p2p_from bigint(20) unsigned NOT NULL,
38
  " );
39
  }
40
 
41
+ static function upgrade() {
42
  global $wpdb;
43
 
44
  $n = 0;
54
  'nopaging' => true
55
  ) );
56
 
57
+ $args['p2p_type'] = array( 0 => 'any' );
58
 
59
  foreach ( get_posts( $args ) as $post ) {
60
  // some connections might be ambiguous, spanning multiple connection types; first one wins
68
  return $n;
69
  }
70
 
71
+ static function uninstall() {
72
  scb_uninstall_table( 'p2p' );
73
  scb_uninstall_table( 'p2pmeta' );
74
 
75
  delete_option( 'p2p_storage' );
76
  }
77
 
78
+ static function deleted_object( $object_id ) {
79
+ $object_type = str_replace( 'deleted_', '', current_filter() );
80
+
81
  foreach ( P2P_Connection_Type_Factory::get_all_instances() as $p2p_type => $ctype ) {
82
  foreach ( array( 'from', 'to' ) as $direction ) {
83
+ if ( $object_type == $ctype->object[ $direction ] ) {
84
  p2p_delete_connections( $p2p_type, array(
85
+ $direction => $object_id,
86
  ) );
87
  }
88
  }
core/type.php CHANGED
@@ -85,7 +85,7 @@ class Generic_Connection_Type {
85
  public function __call( $method, $args ) {
86
  $directed = $this->find_direction( $args[0] );
87
  if ( !$directed ) {
88
- trigger_error( "Can't determine direction", E_USER_WARNING );
89
  return false;
90
  }
91
 
@@ -182,6 +182,26 @@ class Generic_Connection_Type {
182
  array_push( $posts[ $outer_item_id ]->$prop_name, $inner_item );
183
  }
184
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  }
186
 
187
 
@@ -226,6 +246,11 @@ class P2P_Connection_Type extends Generic_Connection_Type {
226
  ) );
227
  }
228
 
 
 
 
 
 
229
  /**
230
  * Get the previous post in an ordered connection.
231
  *
@@ -234,7 +259,7 @@ class P2P_Connection_Type extends Generic_Connection_Type {
234
  *
235
  * @return bool|object False on failure, post object on success
236
  */
237
- public function get_previous( $from, $to ) {
238
  return $this->get_adjacent( $from, $to, -1 );
239
  }
240
 
85
  public function __call( $method, $args ) {
86
  $directed = $this->find_direction( $args[0] );
87
  if ( !$directed ) {
88
+ trigger_error( sprintf( "Can't determine direction for '%s' type.", $this->name ), E_USER_WARNING );
89
  return false;
90
  }
91
 
182
  array_push( $posts[ $outer_item_id ]->$prop_name, $inner_item );
183
  }
184
  }
185
+
186
+ public function get_desc() {
187
+ foreach ( array( 'from', 'to' ) as $key ) {
188
+ $$key = $this->side[ $key ]->get_desc();
189
+ }
190
+
191
+ if ( $this->indeterminate )
192
+ $arrow = '&harr;';
193
+ else
194
+ $arrow = '&rarr;';
195
+
196
+ $label = "$from $arrow $to";
197
+
198
+ $title = $this->title[ 'from' ];
199
+
200
+ if ( $title )
201
+ $label .= " ($title)";
202
+
203
+ return $label;
204
+ }
205
  }
206
 
207
 
246
  ) );
247
  }
248
 
249
+ /** Alias for get_prev() */
250
+ public function get_previous( $from, $to ) {
251
+ return $this->get_prev( $from, $to );
252
+ }
253
+
254
  /**
255
  * Get the previous post in an ordered connection.
256
  *
259
  *
260
  * @return bool|object False on failure, post object on success
261
  */
262
+ public function get_prev( $from, $to ) {
263
  return $this->get_adjacent( $from, $to, -1 );
264
  }
265
 
core/widget.php CHANGED
@@ -27,7 +27,7 @@ class P2P_Widget extends scbWidget {
27
  if ( ! $ctype instanceof P2P_Connection_Type )
28
  continue;
29
 
30
- $ctypes[ $p2p_type ] = self::ctype_label( $ctype );
31
  }
32
 
33
  echo html( 'p', $this->input( array(
@@ -94,30 +94,5 @@ class P2P_Widget extends scbWidget {
94
 
95
  echo $after_widget;
96
  }
97
-
98
- private static function ctype_label( $ctype ) {
99
- foreach ( array( 'from', 'to' ) as $key ) {
100
- $$key = implode( ', ', array_map( array( __CLASS__, 'post_type_label' ), $ctype->$key ) );
101
- }
102
-
103
- if ( $ctype->indeterminate )
104
- $arrow = '&harr;';
105
- else
106
- $arrow = '&rarr;';
107
-
108
- $label = "$from $arrow $to";
109
-
110
- $title = $ctype->title[ 'from' ];
111
-
112
- if ( $title )
113
- $label .= " ($title)";
114
-
115
- return $label;
116
- }
117
-
118
- private static function post_type_label( $post_type ) {
119
- $cpt = get_post_type_object( $post_type );
120
- return $cpt ? $cpt->label : $post_type;
121
- }
122
  }
123
 
27
  if ( ! $ctype instanceof P2P_Connection_Type )
28
  continue;
29
 
30
+ $ctypes[ $p2p_type ] = $ctype->get_desc();
31
  }
32
 
33
  echo html( 'p', $this->input( array(
94
 
95
  echo $after_widget;
96
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  }
98
 
lang/posts-to-posts-ro_RO.mo CHANGED
Binary file
lang/posts-to-posts-ro_RO.po CHANGED
@@ -7,8 +7,8 @@ msgid ""
7
  msgstr ""
8
  "Project-Id-Version: Posts 2 Posts\n"
9
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
10
- "POT-Creation-Date: 2012-03-07 20:34:30+00:00\n"
11
- "PO-Revision-Date: 2012-03-07 22:35+0200\n"
12
  "Last-Translator: scribu <mail@scribu.net>\n"
13
  "Language-Team: ROMANIAN <LL@li.org>\n"
14
  "Language: \n"
@@ -16,82 +16,114 @@ msgstr ""
16
  "Content-Type: text/plain; charset=UTF-8\n"
17
  "Content-Transfer-Encoding: 8bit\n"
18
 
19
- #: admin/box-factory.php:78
20
  msgid " (from)"
21
  msgstr "(de la)"
22
 
23
- #: admin/box-factory.php:79
24
  msgid " (to)"
25
  msgstr "(la)"
26
 
27
- #: admin/box.php:40
28
  msgid "Are you sure you want to delete all connections?"
29
  msgstr "Sigur vreți să ștergeți toate conexiunile?"
30
 
31
- #: admin/box.php:118
32
  msgid "Create connections:"
33
  msgstr "Creează conexiuni:"
34
 
35
- #: admin/box.php:127
36
  msgid "View All"
37
  msgstr "Vezi toate"
38
 
39
- #: admin/box.php:132
40
  msgid "Search"
41
  msgstr "Căutare"
42
 
43
- #: admin/box.php:203
44
  msgid "previous"
45
  msgstr "anterioare"
46
 
47
- #: admin/box.php:204
48
  msgid "next"
49
  msgstr "următoare"
50
 
51
- #: admin/box.php:205
52
  msgid "of"
53
  msgstr "din"
54
 
55
- #: admin/box.php:246
56
  msgid "Can't create connection."
57
  msgstr "Conexiunea nu poate fi creată."
58
 
59
- #: admin/fields.php:14
60
  msgid "Create connection"
61
  msgstr "Crează conexiune"
62
 
63
- #: admin/fields.php:27
64
  msgid "Delete all connections"
65
  msgstr "Șterge toate conexiunile"
66
 
67
- #: admin/fields.php:36
68
  msgid "Delete connection"
69
  msgstr "Șterge conexiune"
70
 
71
- #: core/side.php:140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  msgid "Users"
73
  msgstr "Utilizatori"
74
 
75
- #: core/side.php:145
76
  msgid "User"
77
  msgstr "Utilizator"
78
 
79
- #: core/side.php:146
80
  msgid "Search Users"
81
  msgstr "Caută utilizatori"
82
 
83
- #: core/side.php:147
84
  msgid "No users found."
85
  msgstr "Niciun utilizator găsit."
86
 
87
- #: core/storage.php:35
88
- msgid "Upgraded %d connections."
89
- msgstr "Am actualizat %d conexiuni."
90
-
91
- #: core/storage.php:38
92
- msgid "The Posts 2 Posts connections need to be upgraded. <a href=\"%s\">Proceed.</a>"
93
- msgstr "Conexiunile Posts 2 Posts trebuie actualizate. <a href=\"%s\">Pornește.</a>"
94
-
95
  #: core/type.php:77
96
  msgid "Connected %s"
97
  msgstr "%s conectate"
7
  msgstr ""
8
  "Project-Id-Version: Posts 2 Posts\n"
9
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
10
+ "POT-Creation-Date: 2012-04-06 20:57:17+00:00\n"
11
+ "PO-Revision-Date: 2012-04-06 23:59+0200\n"
12
  "Last-Translator: scribu <mail@scribu.net>\n"
13
  "Language-Team: ROMANIAN <LL@li.org>\n"
14
  "Language: \n"
16
  "Content-Type: text/plain; charset=UTF-8\n"
17
  "Content-Transfer-Encoding: 8bit\n"
18
 
19
+ #: admin/box-factory.php:75
20
  msgid " (from)"
21
  msgstr "(de la)"
22
 
23
+ #: admin/box-factory.php:76
24
  msgid " (to)"
25
  msgstr "(la)"
26
 
27
+ #: admin/box.php:34
28
  msgid "Are you sure you want to delete all connections?"
29
  msgstr "Sigur vreți să ștergeți toate conexiunile?"
30
 
31
+ #: admin/box.php:120
32
  msgid "Create connections:"
33
  msgstr "Creează conexiuni:"
34
 
35
+ #: admin/box.php:129
36
  msgid "View All"
37
  msgstr "Vezi toate"
38
 
39
+ #: admin/box.php:134
40
  msgid "Search"
41
  msgstr "Căutare"
42
 
43
+ #: admin/box.php:205
44
  msgid "previous"
45
  msgstr "anterioare"
46
 
47
+ #: admin/box.php:206
48
  msgid "next"
49
  msgstr "următoare"
50
 
51
+ #: admin/box.php:207
52
  msgid "of"
53
  msgstr "din"
54
 
55
+ #: admin/box.php:248
56
  msgid "Can't create connection."
57
  msgstr "Conexiunea nu poate fi creată."
58
 
59
+ #: admin/fields.php:13
60
  msgid "Create connection"
61
  msgstr "Crează conexiune"
62
 
63
+ #: admin/fields.php:25
64
  msgid "Delete all connections"
65
  msgstr "Șterge toate conexiunile"
66
 
67
+ #: admin/fields.php:34
68
  msgid "Delete connection"
69
  msgstr "Șterge conexiune"
70
 
71
+ #: admin/tools.php:7
72
+ msgid "Connection Types"
73
+ msgstr "Tipuri de conexiuni:"
74
+
75
+ #: admin/tools.php:31
76
+ msgid "Upgraded %d connections."
77
+ msgstr "Am actualizat %d conexiuni."
78
+
79
+ #: admin/tools.php:34
80
+ msgid "The Posts 2 Posts connections need to be upgraded. <a href=\"%s\">Proceed.</a>"
81
+ msgstr "Conexiunile Posts 2 Posts trebuie actualizate. <a href=\"%s\">Pornește.</a>"
82
+
83
+ #: admin/tools.php:54
84
+ msgid "<em>%s</em> is not a registered connection type."
85
+ msgstr "<em>%s</em> nu e un tip de conexiune înregistrat."
86
+
87
+ #: admin/tools.php:63
88
+ msgid "Converted %1$s connections from <em>%2$s</em> to <em>%3$s</em>."
89
+ msgstr "Am convertit %1$s conexiuni din <em>%2$s</em> în <em>%3$s</em>."
90
+
91
+ #: admin/tools.php:77
92
+ msgid "Name"
93
+ msgstr "Nume"
94
+
95
+ #: admin/tools.php:78
96
+ msgid "Information"
97
+ msgstr "Informații"
98
+
99
+ #: admin/tools.php:79
100
+ msgid "Connections"
101
+ msgstr "Conexiuni"
102
+
103
+ #: admin/tools.php:94
104
+ msgid "Convert to registered connection type:"
105
+ msgstr "Convertește într-un tip de conexiune înregistrat:"
106
+
107
+ #: admin/tools.php:129
108
+ msgid "Go"
109
+ msgstr "Go"
110
+
111
+ #: core/side.php:149
112
  msgid "Users"
113
  msgstr "Utilizatori"
114
 
115
+ #: core/side.php:158
116
  msgid "User"
117
  msgstr "Utilizator"
118
 
119
+ #: core/side.php:159
120
  msgid "Search Users"
121
  msgstr "Caută utilizatori"
122
 
123
+ #: core/side.php:160
124
  msgid "No users found."
125
  msgstr "Niciun utilizator găsit."
126
 
 
 
 
 
 
 
 
 
127
  #: core/type.php:77
128
  msgid "Connected %s"
129
  msgstr "%s conectate"
lang/posts-to-posts.pot CHANGED
@@ -4,7 +4,7 @@ msgid ""
4
  msgstr ""
5
  "Project-Id-Version: \n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
7
- "POT-Creation-Date: 2012-03-07 20:34:30+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -12,82 +12,114 @@ msgstr ""
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
- #: admin/box-factory.php:78
16
  msgid " (from)"
17
  msgstr ""
18
 
19
- #: admin/box-factory.php:79
20
  msgid " (to)"
21
  msgstr ""
22
 
23
- #: admin/box.php:40
24
  msgid "Are you sure you want to delete all connections?"
25
  msgstr ""
26
 
27
- #: admin/box.php:118
28
  msgid "Create connections:"
29
  msgstr ""
30
 
31
- #: admin/box.php:127
32
  msgid "View All"
33
  msgstr ""
34
 
35
- #: admin/box.php:132
36
  msgid "Search"
37
  msgstr ""
38
 
39
- #: admin/box.php:203
40
  msgid "previous"
41
  msgstr ""
42
 
43
- #: admin/box.php:204
44
  msgid "next"
45
  msgstr ""
46
 
47
- #: admin/box.php:205
48
  msgid "of"
49
  msgstr ""
50
 
51
- #: admin/box.php:246
52
  msgid "Can't create connection."
53
  msgstr ""
54
 
55
- #: admin/fields.php:14
56
  msgid "Create connection"
57
  msgstr ""
58
 
59
- #: admin/fields.php:27
60
  msgid "Delete all connections"
61
  msgstr ""
62
 
63
- #: admin/fields.php:36
64
  msgid "Delete connection"
65
  msgstr ""
66
 
67
- #: core/side.php:140
68
- msgid "Users"
69
  msgstr ""
70
 
71
- #: core/side.php:145
72
- msgid "User"
73
  msgstr ""
74
 
75
- #: core/side.php:146
76
- msgid "Search Users"
 
 
77
  msgstr ""
78
 
79
- #: core/side.php:147
80
- msgid "No users found."
81
  msgstr ""
82
 
83
- #: core/storage.php:35
84
- msgid "Upgraded %d connections."
85
  msgstr ""
86
 
87
- #: core/storage.php:38
88
- msgid ""
89
- "The Posts 2 Posts connections need to be upgraded. <a href=\"%s\">Proceed.</"
90
- "a>"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  msgstr ""
92
 
93
  #: core/type.php:77
4
  msgstr ""
5
  "Project-Id-Version: \n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
7
+ "POT-Creation-Date: 2012-04-06 20:57:17+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
+ #: admin/box-factory.php:75
16
  msgid " (from)"
17
  msgstr ""
18
 
19
+ #: admin/box-factory.php:76
20
  msgid " (to)"
21
  msgstr ""
22
 
23
+ #: admin/box.php:34
24
  msgid "Are you sure you want to delete all connections?"
25
  msgstr ""
26
 
27
+ #: admin/box.php:120
28
  msgid "Create connections:"
29
  msgstr ""
30
 
31
+ #: admin/box.php:129
32
  msgid "View All"
33
  msgstr ""
34
 
35
+ #: admin/box.php:134
36
  msgid "Search"
37
  msgstr ""
38
 
39
+ #: admin/box.php:205
40
  msgid "previous"
41
  msgstr ""
42
 
43
+ #: admin/box.php:206
44
  msgid "next"
45
  msgstr ""
46
 
47
+ #: admin/box.php:207
48
  msgid "of"
49
  msgstr ""
50
 
51
+ #: admin/box.php:248
52
  msgid "Can't create connection."
53
  msgstr ""
54
 
55
+ #: admin/fields.php:13
56
  msgid "Create connection"
57
  msgstr ""
58
 
59
+ #: admin/fields.php:25
60
  msgid "Delete all connections"
61
  msgstr ""
62
 
63
+ #: admin/fields.php:34
64
  msgid "Delete connection"
65
  msgstr ""
66
 
67
+ #: admin/tools.php:7
68
+ msgid "Connection Types"
69
  msgstr ""
70
 
71
+ #: admin/tools.php:31
72
+ msgid "Upgraded %d connections."
73
  msgstr ""
74
 
75
+ #: admin/tools.php:34
76
+ msgid ""
77
+ "The Posts 2 Posts connections need to be upgraded. <a href=\"%s\">Proceed.</"
78
+ "a>"
79
  msgstr ""
80
 
81
+ #: admin/tools.php:54
82
+ msgid "<em>%s</em> is not a registered connection type."
83
  msgstr ""
84
 
85
+ #: admin/tools.php:63
86
+ msgid "Converted %1$s connections from <em>%2$s</em> to <em>%3$s</em>."
87
  msgstr ""
88
 
89
+ #: admin/tools.php:77
90
+ msgid "Name"
91
+ msgstr ""
92
+
93
+ #: admin/tools.php:78
94
+ msgid "Information"
95
+ msgstr ""
96
+
97
+ #: admin/tools.php:79
98
+ msgid "Connections"
99
+ msgstr ""
100
+
101
+ #: admin/tools.php:94
102
+ msgid "Convert to registered connection type:"
103
+ msgstr ""
104
+
105
+ #: admin/tools.php:129
106
+ msgid "Go"
107
+ msgstr ""
108
+
109
+ #: core/side.php:149
110
+ msgid "Users"
111
+ msgstr ""
112
+
113
+ #: core/side.php:158
114
+ msgid "User"
115
+ msgstr ""
116
+
117
+ #: core/side.php:159
118
+ msgid "Search Users"
119
+ msgstr ""
120
+
121
+ #: core/side.php:160
122
+ msgid "No users found."
123
  msgstr ""
124
 
125
  #: core/type.php:77
posts-to-posts.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Posts 2 Posts
4
  Description: Create many-to-many relationships between all types of posts.
5
- Version: 1.1.6
6
  Author: scribu
7
  Author URI: http://scribu.net/
8
  Plugin URI: http://scribu.net/wordpress/posts-to-posts
@@ -26,7 +26,7 @@ You should have received a copy of the GNU General Public License
26
  along with this program. If not, see <http://www.gnu.org/licenses/>.
27
  */
28
 
29
- define( 'P2P_PLUGIN_VERSION', '1.1.6' );
30
 
31
  define( 'P2P_TEXTDOMAIN', 'posts-to-posts' );
32
 
@@ -47,9 +47,10 @@ function _p2p_init() {
47
 
48
  if ( is_admin() ) {
49
  _p2p_load_files( "$base/admin", array(
50
- 'utils',
51
  'box-factory', 'box', 'fields',
52
- 'column-factory', 'column'
 
53
  ) );
54
  }
55
 
2
  /*
3
  Plugin Name: Posts 2 Posts
4
  Description: Create many-to-many relationships between all types of posts.
5
+ Version: 1.2
6
  Author: scribu
7
  Author URI: http://scribu.net/
8
  Plugin URI: http://scribu.net/wordpress/posts-to-posts
26
  along with this program. If not, see <http://www.gnu.org/licenses/>.
27
  */
28
 
29
+ define( 'P2P_PLUGIN_VERSION', '1.2' );
30
 
31
  define( 'P2P_TEXTDOMAIN', 'posts-to-posts' );
32
 
47
 
48
  if ( is_admin() ) {
49
  _p2p_load_files( "$base/admin", array(
50
+ 'mustache',
51
  'box-factory', 'box', 'fields',
52
+ 'column-factory', 'column',
53
+ 'tools'
54
  ) );
55
  }
56
 
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: scribu, ciobi
3
  Tags: connections, custom post types, relationships, many-to-many, users
4
  Requires at least: 3.2
5
  Tested up to: 3.3
6
- Stable tag: 1.1.6
7
 
8
  Efficient many-to-many connections between posts, pages, custom post types, users.
9
 
@@ -19,8 +19,7 @@ Additionally, you can create many-to-many relationships between posts and users.
19
 
20
  * favorite posts of users
21
  * multiple authors per post
22
-
23
- etc.
24
 
25
  Links: [**Documentation**](http://github.com/scribu/wp-posts-to-posts/wiki) | [Plugin News](http://scribu.net/wordpress/posts-to-posts) | [Author's Site](http://scribu.net)
26
 
@@ -47,9 +46,20 @@ Make sure your host is running PHP 5. The only foolproof way to do this is to ad
47
  2. Advanced connection metabox
48
  3. Admin column
49
  4. Widget
 
50
 
51
  == Changelog ==
52
 
 
 
 
 
 
 
 
 
 
 
53
  = 1.1.6 =
54
  * convert "View All" tab into button
55
  * refresh candidate list after deleting a connection
3
  Tags: connections, custom post types, relationships, many-to-many, users
4
  Requires at least: 3.2
5
  Tested up to: 3.3
6
+ Stable tag: 1.2
7
 
8
  Efficient many-to-many connections between posts, pages, custom post types, users.
9
 
19
 
20
  * favorite posts of users
21
  * multiple authors per post
22
+ * etc.
 
23
 
24
  Links: [**Documentation**](http://github.com/scribu/wp-posts-to-posts/wiki) | [Plugin News](http://scribu.net/wordpress/posts-to-posts) | [Author's Site](http://scribu.net)
25
 
46
  2. Advanced connection metabox
47
  3. Admin column
48
  4. Widget
49
+ 5. Connection Types screen
50
 
51
  == Changelog ==
52
 
53
+ = 1.2 =
54
+ * added Tools -> Connection Types admin screen
55
+ * fixed migration script
56
+ * made p2p_get_connections() accept arrays of ids
57
+ * added 'separator' parameter to p2p_list_posts()
58
+ * made P2P_Directed_Type->connect() return WP_Error instances instead of just false
59
+ * when a user is deleted, delete all the associated connections
60
+ * fixed conflict with bbPress Topics for Posts plugin
61
+ * [more info](http://scribu.net/wordpress/posts-to-posts/p2p-1-2.html)
62
+
63
  = 1.1.6 =
64
  * convert "View All" tab into button
65
  * refresh candidate list after deleting a connection
scb/Forms.php CHANGED
@@ -43,6 +43,7 @@ class scbForms {
43
  'desc' => '',
44
  'desc_pos' => 'after',
45
  'wrap' => self::TOKEN,
 
46
  ) );
47
 
48
  if ( isset( $args['value'] ) && is_array( $args['value'] ) ) {
@@ -184,16 +185,15 @@ class scbForms {
184
 
185
  $opts = '';
186
  foreach ( $values as $value => $title ) {
187
- if ( empty( $value ) || empty( $title ) )
188
- continue;
189
-
190
- $opts .= self::_checkbox( array(
191
  'type' => 'checkbox',
192
  'value' => $value,
193
  'checked' => in_array( $value, $checked ),
194
  'desc' => $title,
195
  'desc_pos' => 'after'
196
  ) );
 
 
197
  }
198
 
199
  return self::add_desc( $opts, $desc, $desc_pos );
@@ -222,16 +222,15 @@ class scbForms {
222
 
223
  $opts = '';
224
  foreach ( $values as $value => $title ) {
225
- if ( empty( $value ) || empty( $title ) )
226
- continue;
227
-
228
- $opts .= self::_checkbox( array(
229
  'type' => 'radio',
230
  'value' => $value,
231
  'checked' => ( (string) $value == (string) $selected ),
232
  'desc' => $title,
233
  'desc_pos' => 'after'
234
  ) );
 
 
235
  }
236
 
237
  return self::add_desc( $opts, $desc, $desc_pos );
@@ -239,7 +238,7 @@ class scbForms {
239
 
240
  private static function _select( $args ) {
241
  extract( wp_parse_args( $args, array(
242
- 'text' => '',
243
  'extra' => array()
244
  ) ) );
245
 
@@ -254,9 +253,6 @@ class scbForms {
254
  }
255
 
256
  foreach ( $values as $value => $title ) {
257
- if ( empty( $value ) || empty( $title ) )
258
- continue;
259
-
260
  $options[] = array(
261
  'value' => $value,
262
  'selected' => ( (string) $value == (string) $selected ),
43
  'desc' => '',
44
  'desc_pos' => 'after',
45
  'wrap' => self::TOKEN,
46
+ 'wrap_each' => self::TOKEN,
47
  ) );
48
 
49
  if ( isset( $args['value'] ) && is_array( $args['value'] ) ) {
185
 
186
  $opts = '';
187
  foreach ( $values as $value => $title ) {
188
+ $single_input = self::_checkbox( array(
 
 
 
189
  'type' => 'checkbox',
190
  'value' => $value,
191
  'checked' => in_array( $value, $checked ),
192
  'desc' => $title,
193
  'desc_pos' => 'after'
194
  ) );
195
+
196
+ $opts .= str_replace( self::TOKEN, $single_input, $args['wrap_each'] );
197
  }
198
 
199
  return self::add_desc( $opts, $desc, $desc_pos );
222
 
223
  $opts = '';
224
  foreach ( $values as $value => $title ) {
225
+ $single_input = self::_checkbox( array(
 
 
 
226
  'type' => 'radio',
227
  'value' => $value,
228
  'checked' => ( (string) $value == (string) $selected ),
229
  'desc' => $title,
230
  'desc_pos' => 'after'
231
  ) );
232
+
233
+ $opts .= str_replace( self::TOKEN, $single_input, $args['wrap_each'] );
234
  }
235
 
236
  return self::add_desc( $opts, $desc, $desc_pos );
238
 
239
  private static function _select( $args ) {
240
  extract( wp_parse_args( $args, array(
241
+ 'text' => false,
242
  'extra' => array()
243
  ) ) );
244
 
253
  }
254
 
255
  foreach ( $values as $value => $title ) {
 
 
 
256
  $options[] = array(
257
  'value' => $value,
258
  'selected' => ( (string) $value == (string) $selected ),
scb/load.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
 
3
- $GLOBALS['_scb_data'] = array( 51, __FILE__, array(
4
  'scbUtil', 'scbOptions', 'scbForms', 'scbTable',
5
  'scbWidget', 'scbAdminPage', 'scbBoxesPage',
6
  'scbCron', 'scbHooks',
1
  <?php
2
 
3
+ $GLOBALS['_scb_data'] = array( 52, __FILE__, array(
4
  'scbUtil', 'scbOptions', 'scbForms', 'scbTable',
5
  'scbWidget', 'scbAdminPage', 'scbBoxesPage',
6
  'scbCron', 'scbHooks',
screenshot-5.png ADDED
Binary file