Version Description
- convert "View All" tab into button
- refresh candidate list after deleting a connection
- fix cardinality check
- introduce 'p2p_connection_type_args' filter
- make 'connected_type' accept an array of connection type names
- inadvertently remove support for queries without 'connected_type' parameter
Download this release
Release Info
Developer | scribu |
Plugin | Posts 2 Posts |
Version | 1.1.6 |
Comparing to | |
See all releases |
Code changes from version 1.0.1 to 1.1.6
- admin/box-factory.php +48 -38
- admin/box.css +24 -11
- admin/box.js +89 -80
- admin/box.php +61 -79
- admin/column-factory.php +26 -6
- admin/column.php +32 -8
- admin/fields.php +70 -40
- admin/templates/box.html +6 -4
- admin/templates/column-create.html +1 -1
- admin/templates/column-delete-all.html +1 -1
- admin/templates/column-delete.html +1 -1
- admin/templates/column-title.html +1 -1
- admin/templates/tab-create-post.html +1 -1
- admin/templates/tab-search.html +3 -1
- core/api.php +202 -55
- core/directed-type.php +152 -97
- core/ordered-type.php +0 -27
- core/query-post.php +70 -0
- core/query-user.php +56 -0
- core/query.php +129 -72
- core/side.php +199 -0
- core/storage.php +79 -174
- core/type-factory.php +100 -0
- core/type.php +102 -101
- core/url-query.php +5 -22
- core/util.php +41 -105
- core/widget.php +13 -6
- lang/posts-to-posts-de_DE.mo +0 -0
- lang/posts-to-posts-de_DE.po +133 -0
- lang/posts-to-posts-ro_RO.mo +0 -0
- lang/posts-to-posts-ro_RO.po +65 -37
- lang/posts-to-posts-sv_SE.mo +0 -0
- lang/posts-to-posts-sv_SE.po +90 -0
- lang/posts-to-posts-tr_TR.mo +0 -0
- lang/posts-to-posts-tr_TR.po +114 -0
- lang/posts-to-posts.pot +61 -31
- mustache/Mustache.php +31 -13
- mustache/README.markdown +48 -42
- posts-to-posts.php +8 -6
- readme.txt +54 -6
- scb/AdminPage.php +27 -15
- scb/BoxesPage.php +6 -4
- scb/Cron.php +1 -1
- scb/Forms.php +152 -70
- scb/Options.php +2 -7
- scb/Table.php +45 -26
- scb/Util.php +20 -2
- scb/load.php +7 -2
- screenshot-1.png +0 -0
admin/box-factory.php
CHANGED
@@ -9,8 +9,36 @@ class P2P_Box_Factory {
|
|
9 |
|
10 |
private static $box_args = array();
|
11 |
|
12 |
-
static function
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
return false;
|
15 |
|
16 |
$box_args = (object) wp_parse_args( $box_args, array(
|
@@ -33,20 +61,14 @@ class P2P_Box_Factory {
|
|
33 |
$field_args['values'] = array( true => ' ' );
|
34 |
}
|
35 |
|
36 |
-
self::$box_args[$
|
37 |
|
38 |
return true;
|
39 |
}
|
40 |
|
41 |
-
static function init() {
|
42 |
-
add_action( 'add_meta_boxes', array( __CLASS__, 'add_meta_boxes' ) );
|
43 |
-
add_action( 'save_post', array( __CLASS__, 'save_post' ), 10, 2 );
|
44 |
-
add_action( 'wp_ajax_p2p_box', array( __CLASS__, 'wp_ajax_p2p_box' ) );
|
45 |
-
}
|
46 |
-
|
47 |
static function add_meta_boxes( $post_type ) {
|
48 |
-
foreach ( self::$box_args as $
|
49 |
-
$ctype = p2p_type( $
|
50 |
|
51 |
$dir = self::get_visible_directions( $post_type, $ctype, $box_args->show );
|
52 |
|
@@ -68,7 +90,7 @@ class P2P_Box_Factory {
|
|
68 |
continue;
|
69 |
|
70 |
add_meta_box(
|
71 |
-
"p2p-{$direction}-{$ctype->
|
72 |
$title[$key],
|
73 |
array( $box, 'render' ),
|
74 |
$post_type,
|
@@ -87,10 +109,7 @@ class P2P_Box_Factory {
|
|
87 |
return array();
|
88 |
|
89 |
if ( $ctype->indeterminate && !$ctype->reciprocal ) {
|
90 |
-
|
91 |
-
return array( 'from', 'to' );
|
92 |
-
else
|
93 |
-
return array( $show_ui );
|
94 |
}
|
95 |
|
96 |
if ( 'any' == $show_ui || $direction == $show_ui )
|
@@ -107,31 +126,22 @@ class P2P_Box_Factory {
|
|
107 |
return;
|
108 |
|
109 |
// Custom fields
|
110 |
-
if ( isset( $_POST['
|
111 |
-
foreach ( $_POST['
|
112 |
-
$ctype = p2p_type( $
|
113 |
if ( !$ctype )
|
114 |
continue;
|
115 |
|
116 |
-
foreach ( $ctype->
|
117 |
-
$
|
118 |
-
$data = scbForms::get_value( array( 'p2p_meta', $p2p_id ), $_POST, array() );
|
119 |
-
|
120 |
-
foreach ( self::$box_args[$ctype_id]->fields as $key => $field_args ) {
|
121 |
-
if ( 'checkbox' == $field_args['type'] ) {
|
122 |
-
$new_values = scbForms::get_value( $key, $data, array() );
|
123 |
|
124 |
-
|
|
|
|
|
125 |
|
126 |
-
|
127 |
-
p2p_add_meta( $p2p_id, $key, $value );
|
128 |
|
129 |
-
|
130 |
-
p2p_delete_meta( $p2p_id, $key, $value );
|
131 |
-
} else {
|
132 |
-
p2p_update_meta( $p2p_id, $key, $data[$key] );
|
133 |
-
}
|
134 |
-
}
|
135 |
}
|
136 |
}
|
137 |
}
|
@@ -152,8 +162,8 @@ class P2P_Box_Factory {
|
|
152 |
static function wp_ajax_p2p_box() {
|
153 |
check_ajax_referer( P2P_BOX_NONCE, 'nonce' );
|
154 |
|
155 |
-
$ctype = p2p_type( $_REQUEST['
|
156 |
-
if ( !$ctype || !isset( self::$box_args[$ctype->
|
157 |
die(0);
|
158 |
|
159 |
$post_type = get_post_type( $_REQUEST['from'] );
|
@@ -164,7 +174,7 @@ class P2P_Box_Factory {
|
|
164 |
if ( !$directed )
|
165 |
die(0);
|
166 |
|
167 |
-
$box = new P2P_Box( self::$box_args[$ctype->
|
168 |
|
169 |
if ( !$box->check_capability() )
|
170 |
die(-1);
|
9 |
|
10 |
private static $box_args = array();
|
11 |
|
12 |
+
static function init() {
|
13 |
+
add_filter( 'p2p_connection_type_args', array( __CLASS__, 'filter_args' ) );
|
14 |
+
|
15 |
+
add_action( 'add_meta_boxes', array( __CLASS__, 'add_meta_boxes' ) );
|
16 |
+
add_action( 'save_post', array( __CLASS__, 'save_post' ), 10, 2 );
|
17 |
+
add_action( 'wp_ajax_p2p_box', array( __CLASS__, 'wp_ajax_p2p_box' ) );
|
18 |
+
}
|
19 |
+
|
20 |
+
static function filter_args( $args ) {
|
21 |
+
if ( isset( $args['admin_box'] ) ) {
|
22 |
+
$box_args = _p2p_pluck( $args, 'admin_box' );
|
23 |
+
if ( !is_array( $box_args ) )
|
24 |
+
$box_args = array( 'show' => $box_args );
|
25 |
+
} else {
|
26 |
+
$box_args = array();
|
27 |
+
}
|
28 |
+
|
29 |
+
foreach ( array( 'fields', 'can_create_post' ) as $key ) {
|
30 |
+
if ( isset( $args[ $key ] ) ) {
|
31 |
+
$box_args[ $key ] = _p2p_pluck( $args, $key );
|
32 |
+
}
|
33 |
+
}
|
34 |
+
|
35 |
+
self::register( $args['name'], $box_args );
|
36 |
+
|
37 |
+
return $args;
|
38 |
+
}
|
39 |
+
|
40 |
+
static function register( $p2p_type, $box_args ) {
|
41 |
+
if ( isset( self::$box_args[$p2p_type] ) )
|
42 |
return false;
|
43 |
|
44 |
$box_args = (object) wp_parse_args( $box_args, array(
|
61 |
$field_args['values'] = array( true => ' ' );
|
62 |
}
|
63 |
|
64 |
+
self::$box_args[$p2p_type] = $box_args;
|
65 |
|
66 |
return true;
|
67 |
}
|
68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
static function add_meta_boxes( $post_type ) {
|
70 |
+
foreach ( self::$box_args as $p2p_type => $box_args ) {
|
71 |
+
$ctype = p2p_type( $p2p_type );
|
72 |
|
73 |
$dir = self::get_visible_directions( $post_type, $ctype, $box_args->show );
|
74 |
|
90 |
continue;
|
91 |
|
92 |
add_meta_box(
|
93 |
+
"p2p-{$direction}-{$ctype->name}",
|
94 |
$title[$key],
|
95 |
array( $box, 'render' ),
|
96 |
$post_type,
|
109 |
return array();
|
110 |
|
111 |
if ( $ctype->indeterminate && !$ctype->reciprocal ) {
|
112 |
+
return _p2p_expand_direction( $show_ui );
|
|
|
|
|
|
|
113 |
}
|
114 |
|
115 |
if ( 'any' == $show_ui || $direction == $show_ui )
|
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 |
}
|
162 |
static function wp_ajax_p2p_box() {
|
163 |
check_ajax_referer( P2P_BOX_NONCE, 'nonce' );
|
164 |
|
165 |
+
$ctype = p2p_type( $_REQUEST['p2p_type'] );
|
166 |
+
if ( !$ctype || !isset( self::$box_args[$ctype->name] ) )
|
167 |
die(0);
|
168 |
|
169 |
$post_type = get_post_type( $_REQUEST['from'] );
|
174 |
if ( !$directed )
|
175 |
die(0);
|
176 |
|
177 |
+
$box = new P2P_Box( self::$box_args[$ctype->name], $directed, $post_type );
|
178 |
|
179 |
if ( !$box->check_capability() )
|
180 |
die(-1);
|
admin/box.css
CHANGED
@@ -2,12 +2,12 @@
|
|
2 |
color: #AAA;
|
3 |
}
|
4 |
|
5 |
-
.p2p-
|
6 |
-
|
7 |
}
|
8 |
|
9 |
-
.p2p-connections
|
10 |
-
|
11 |
}
|
12 |
|
13 |
/* Tabs */
|
@@ -23,12 +23,12 @@
|
|
23 |
display: block;
|
24 |
}
|
25 |
|
26 |
-
|
27 |
-
|
28 |
-
.p2p-connections {
|
29 |
-
margin-top: 4px;
|
30 |
}
|
31 |
|
|
|
|
|
32 |
.p2p-results,
|
33 |
.p2p-connections {
|
34 |
background-color: #F9F9F9;
|
@@ -40,9 +40,14 @@
|
|
40 |
width: 100%;
|
41 |
}
|
42 |
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
.p2p-search + .p2p-results,
|
44 |
-
.p2p-results + .p2p-navigation
|
45 |
-
.p2p-tab-create-post .button {
|
46 |
margin-top: 8px;
|
47 |
}
|
48 |
|
@@ -125,6 +130,13 @@ td.p2p-col-create {
|
|
125 |
background: url("images/delete.png") no-repeat scroll 50% 50% transparent;
|
126 |
}
|
127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
td.p2p-col-order {
|
129 |
width: 13px;
|
130 |
}
|
@@ -147,7 +159,8 @@ tr:hover td.p2p-col-order {
|
|
147 |
}
|
148 |
|
149 |
.p2p-tab-create-post input[type="text"] {
|
150 |
-
width:
|
|
|
151 |
}
|
152 |
|
153 |
#side-sortables .p2p-notice {
|
2 |
color: #AAA;
|
3 |
}
|
4 |
|
5 |
+
.p2p-box a {
|
6 |
+
text-decoration: none;
|
7 |
}
|
8 |
|
9 |
+
.p2p-create-connections p {
|
10 |
+
margin-bottom: .5em;
|
11 |
}
|
12 |
|
13 |
/* Tabs */
|
23 |
display: block;
|
24 |
}
|
25 |
|
26 |
+
.tabs-panel {
|
27 |
+
border-radius: 0 3px 3px 3px;
|
|
|
|
|
28 |
}
|
29 |
|
30 |
+
/* Connections */
|
31 |
+
|
32 |
.p2p-results,
|
33 |
.p2p-connections {
|
34 |
background-color: #F9F9F9;
|
40 |
width: 100%;
|
41 |
}
|
42 |
|
43 |
+
.p2p-box .tabs-panel button {
|
44 |
+
clear: both;
|
45 |
+
display: block;
|
46 |
+
margin-top: 8px;
|
47 |
+
}
|
48 |
+
|
49 |
.p2p-search + .p2p-results,
|
50 |
+
.p2p-results + .p2p-navigation {
|
|
|
51 |
margin-top: 8px;
|
52 |
}
|
53 |
|
130 |
background: url("images/delete.png") no-repeat scroll 50% 50% transparent;
|
131 |
}
|
132 |
|
133 |
+
.p2p-col-title img {
|
134 |
+
display: block;
|
135 |
+
margin: 2px 0;
|
136 |
+
max-height: 32px;
|
137 |
+
max-width: 40px;
|
138 |
+
}
|
139 |
+
|
140 |
td.p2p-col-order {
|
141 |
width: 13px;
|
142 |
}
|
159 |
}
|
160 |
|
161 |
.p2p-tab-create-post input[type="text"] {
|
162 |
+
width: 100%;
|
163 |
+
display: block;
|
164 |
}
|
165 |
|
166 |
#side-sortables .p2p-notice {
|
admin/box.js
CHANGED
@@ -21,7 +21,7 @@
|
|
21 |
jQuery('.p2p-search input[placeholder]').each(setVal).focus(clearVal).blur(setVal);
|
22 |
}
|
23 |
return jQuery('.p2p-box').each(function(){
|
24 |
-
var $metabox, $connections, $spinner, ajax_request, row_ajax_request, append_connection, clear_connections, delete_connection, create_connection, switch_to_tab,
|
25 |
$metabox = jQuery(this);
|
26 |
$connections = $metabox.find('.p2p-connections');
|
27 |
$spinner = jQuery('<img>', {
|
@@ -29,29 +29,100 @@
|
|
29 |
'class': 'p2p-spinner'
|
30 |
});
|
31 |
ajax_request = function(data, callback, type){
|
|
|
32 |
type == null && (type = 'POST');
|
33 |
data.action = 'p2p_box';
|
34 |
data.nonce = P2PAdmin.nonce;
|
35 |
-
data.
|
36 |
data.direction = $metabox.data('direction');
|
37 |
data.from = jQuery('#post_ID').val();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
return jQuery.ajax({
|
39 |
type: type,
|
40 |
url: ajaxurl,
|
41 |
data: data,
|
42 |
-
success:
|
43 |
});
|
44 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
row_ajax_request = function($td, data, callback){
|
46 |
$td.html($spinner.show());
|
47 |
return ajax_request(data, callback);
|
48 |
};
|
49 |
-
|
50 |
-
|
|
|
|
|
|
|
|
|
|
|
51 |
if ('one' == $metabox.data('cardinality')) {
|
52 |
return $metabox.find('.p2p-create-connections').hide();
|
53 |
}
|
54 |
};
|
|
|
|
|
|
|
|
|
55 |
clear_connections = function(ev){
|
56 |
var $self, $td, data, _this = this;
|
57 |
if (!confirm(P2PAdmin.deleteConfirmMessage)) {
|
@@ -65,7 +136,7 @@
|
|
65 |
row_ajax_request($td, data, function(response){
|
66 |
$connections.hide().find('tbody').html('');
|
67 |
$td.html($self);
|
68 |
-
return
|
69 |
});
|
70 |
return false;
|
71 |
};
|
@@ -79,10 +150,8 @@
|
|
79 |
};
|
80 |
row_ajax_request($td, data, function(response){
|
81 |
$td.closest('tr').remove();
|
82 |
-
|
83 |
-
|
84 |
-
}
|
85 |
-
return $metabox.find('.p2p-create-connections').show();
|
86 |
});
|
87 |
return false;
|
88 |
};
|
@@ -95,15 +164,10 @@
|
|
95 |
to: $self.data('post_id')
|
96 |
};
|
97 |
row_ajax_request($td, data, function(response){
|
98 |
-
var $table;
|
99 |
append_connection(response);
|
100 |
if ($metabox.data('prevent_duplicates')) {
|
101 |
-
$
|
102 |
-
|
103 |
-
return $table.remove();
|
104 |
-
} else {
|
105 |
-
return $td.closest('tr').remove();
|
106 |
-
}
|
107 |
} else {
|
108 |
return $td.html($self);
|
109 |
}
|
@@ -132,66 +196,11 @@
|
|
132 |
}
|
133 |
});
|
134 |
}
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
this.init_pagination_data();
|
141 |
-
this.tab.delegate('.p2p-prev, .p2p-next', 'click', __bind(this, this.change_page));
|
142 |
-
this.data = {
|
143 |
-
subaction: 'search',
|
144 |
-
s: ''
|
145 |
-
};
|
146 |
-
}
|
147 |
-
prototype.init_pagination_data = function(){
|
148 |
-
this.current_page = this.tab.find('.p2p-current').data('num') || 1;
|
149 |
-
return this.total_pages = this.tab.find('.p2p-total').data('num') || 1;
|
150 |
-
};
|
151 |
-
prototype.change_page = function(ev){
|
152 |
-
var $navButton, new_page;
|
153 |
-
$navButton = jQuery(ev.target);
|
154 |
-
new_page = this.current_page;
|
155 |
-
if ($navButton.hasClass('inactive')) {
|
156 |
-
return false;
|
157 |
-
}
|
158 |
-
if ($navButton.hasClass('p2p-prev')) {
|
159 |
-
new_page--;
|
160 |
-
} else {
|
161 |
-
new_page++;
|
162 |
-
}
|
163 |
-
this.find_posts(new_page);
|
164 |
-
return false;
|
165 |
-
};
|
166 |
-
prototype.find_posts = function(new_page){
|
167 |
-
this.data.paged = new_page
|
168 |
-
? new_page > this.total_pages ? this.current_page : new_page
|
169 |
-
: this.current_page;
|
170 |
-
$spinner.appendTo(this.tab.find('.p2p-navigation'));
|
171 |
-
return ajax_request(this.data, __bind(this, this.update_rows), 'GET');
|
172 |
-
};
|
173 |
-
prototype.update_rows = function(response){
|
174 |
-
$spinner.remove();
|
175 |
-
try {
|
176 |
-
response = jQuery.parseJSON(response);
|
177 |
-
} catch (e) {
|
178 |
-
if (typeof console != 'undefined' && console !== null) {
|
179 |
-
console.error('Malformed response', response);
|
180 |
-
}
|
181 |
-
return;
|
182 |
-
}
|
183 |
-
this.tab.find('.p2p-results, .p2p-navigation, .p2p-notice').remove();
|
184 |
-
if (!response.rows) {
|
185 |
-
return this.tab.append(jQuery('<div class="p2p-notice">').html(response.msg));
|
186 |
-
} else {
|
187 |
-
this.tab.append(response.rows);
|
188 |
-
return this.init_pagination_data();
|
189 |
-
}
|
190 |
-
};
|
191 |
-
return PostsTab;
|
192 |
-
}());
|
193 |
-
searchTab = new PostsTab('.p2p-tab-search');
|
194 |
-
listTab = new PostsTab('.p2p-tab-list');
|
195 |
$searchInput = $metabox.find('.p2p-tab-search :text');
|
196 |
$searchInput.keypress(function(ev){
|
197 |
if (13 === ev.keyCode) {
|
@@ -205,15 +214,15 @@
|
|
205 |
return delayed = setTimeout(function(){
|
206 |
var searchStr;
|
207 |
searchStr = $searchInput.val();
|
208 |
-
if (
|
209 |
return;
|
210 |
}
|
211 |
-
searchTab.
|
212 |
$spinner.insertAfter($searchInput).show();
|
213 |
return searchTab.find_posts(1);
|
214 |
}, 400);
|
215 |
});
|
216 |
-
$createButton = $metabox.find('.p2p-tab-create-post
|
217 |
$createInput = $metabox.find('.p2p-tab-create-post :text');
|
218 |
$createButton.click(function(){
|
219 |
var $button, title, data;
|
21 |
jQuery('.p2p-search input[placeholder]').each(setVal).focus(clearVal).blur(setVal);
|
22 |
}
|
23 |
return jQuery('.p2p-box').each(function(){
|
24 |
+
var $metabox, $connections, $spinner, ajax_request, PostsTab, searchTab, row_ajax_request, maybe_hide_table, append_connection, refresh_candidates, clear_connections, delete_connection, create_connection, switch_to_tab, $viewAll, $searchInput, $createButton, $createInput;
|
25 |
$metabox = jQuery(this);
|
26 |
$connections = $metabox.find('.p2p-connections');
|
27 |
$spinner = jQuery('<img>', {
|
29 |
'class': 'p2p-spinner'
|
30 |
});
|
31 |
ajax_request = function(data, callback, type){
|
32 |
+
var handler;
|
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;
|
40 |
+
data.paged = searchTab.params.paged;
|
41 |
+
handler = function(response){
|
42 |
+
try {
|
43 |
+
response = jQuery.parseJSON(response);
|
44 |
+
return callback(response);
|
45 |
+
} catch (e) {
|
46 |
+
return typeof console != 'undefined' && console !== null ? console.error('Malformed response', response) : void 8;
|
47 |
+
}
|
48 |
+
};
|
49 |
return jQuery.ajax({
|
50 |
type: type,
|
51 |
url: ajaxurl,
|
52 |
data: data,
|
53 |
+
success: handler
|
54 |
});
|
55 |
};
|
56 |
+
PostsTab = (function(){
|
57 |
+
PostsTab.displayName = 'PostsTab';
|
58 |
+
var prototype = PostsTab.prototype, constructor = PostsTab;
|
59 |
+
function PostsTab(selector){
|
60 |
+
this.tab = $metabox.find(selector);
|
61 |
+
this.params = {
|
62 |
+
subaction: 'search',
|
63 |
+
s: ''
|
64 |
+
};
|
65 |
+
this.init_pagination_data();
|
66 |
+
this.tab.delegate('.p2p-prev, .p2p-next', 'click', __bind(this, this.change_page));
|
67 |
+
}
|
68 |
+
prototype.init_pagination_data = function(){
|
69 |
+
this.params.paged = this.tab.find('.p2p-current').data('num') || 1;
|
70 |
+
return this.total_pages = this.tab.find('.p2p-total').data('num') || 1;
|
71 |
+
};
|
72 |
+
prototype.change_page = function(ev){
|
73 |
+
var $navButton, new_page;
|
74 |
+
$navButton = jQuery(ev.target);
|
75 |
+
new_page = this.params.paged;
|
76 |
+
if ($navButton.hasClass('inactive')) {
|
77 |
+
return false;
|
78 |
+
}
|
79 |
+
if ($navButton.hasClass('p2p-prev')) {
|
80 |
+
new_page--;
|
81 |
+
} else {
|
82 |
+
new_page++;
|
83 |
+
}
|
84 |
+
$spinner.appendTo(this.tab.find('.p2p-navigation'));
|
85 |
+
this.find_posts(new_page);
|
86 |
+
return false;
|
87 |
+
};
|
88 |
+
prototype.find_posts = function(new_page){
|
89 |
+
if (0 < new_page && new_page <= this.total_pages) {
|
90 |
+
this.params.paged = new_page;
|
91 |
+
}
|
92 |
+
return ajax_request(this.params, __bind(this, this.update_rows), 'GET');
|
93 |
+
};
|
94 |
+
prototype.update_rows = function(response){
|
95 |
+
$spinner.remove();
|
96 |
+
this.tab.find('button, .p2p-results, .p2p-navigation, .p2p-notice').remove();
|
97 |
+
if (!response.rows) {
|
98 |
+
return this.tab.append(jQuery('<div class="p2p-notice">').html(response.msg));
|
99 |
+
} else {
|
100 |
+
this.tab.append(response.rows);
|
101 |
+
return this.init_pagination_data();
|
102 |
+
}
|
103 |
+
};
|
104 |
+
return PostsTab;
|
105 |
+
}());
|
106 |
+
searchTab = new PostsTab('.p2p-tab-search');
|
107 |
row_ajax_request = function($td, data, callback){
|
108 |
$td.html($spinner.show());
|
109 |
return ajax_request(data, callback);
|
110 |
};
|
111 |
+
maybe_hide_table = function($table){
|
112 |
+
if (!$table.find('tbody tr').length) {
|
113 |
+
return $table.hide();
|
114 |
+
}
|
115 |
+
};
|
116 |
+
append_connection = function(response){
|
117 |
+
$connections.show().find('tbody').append(response.row);
|
118 |
if ('one' == $metabox.data('cardinality')) {
|
119 |
return $metabox.find('.p2p-create-connections').hide();
|
120 |
}
|
121 |
};
|
122 |
+
refresh_candidates = function(results){
|
123 |
+
$metabox.find('.p2p-create-connections').show();
|
124 |
+
return searchTab.update_rows(results);
|
125 |
+
};
|
126 |
clear_connections = function(ev){
|
127 |
var $self, $td, data, _this = this;
|
128 |
if (!confirm(P2PAdmin.deleteConfirmMessage)) {
|
136 |
row_ajax_request($td, data, function(response){
|
137 |
$connections.hide().find('tbody').html('');
|
138 |
$td.html($self);
|
139 |
+
return refresh_candidates(response);
|
140 |
});
|
141 |
return false;
|
142 |
};
|
150 |
};
|
151 |
row_ajax_request($td, data, function(response){
|
152 |
$td.closest('tr').remove();
|
153 |
+
maybe_hide_table($connections);
|
154 |
+
return refresh_candidates(response);
|
|
|
|
|
155 |
});
|
156 |
return false;
|
157 |
};
|
164 |
to: $self.data('post_id')
|
165 |
};
|
166 |
row_ajax_request($td, data, function(response){
|
|
|
167 |
append_connection(response);
|
168 |
if ($metabox.data('prevent_duplicates')) {
|
169 |
+
$td.closest('tr').remove();
|
170 |
+
return maybe_hide_table($td.closest('table'));
|
|
|
|
|
|
|
|
|
171 |
} else {
|
172 |
return $td.html($self);
|
173 |
}
|
196 |
}
|
197 |
});
|
198 |
}
|
199 |
+
$viewAll = $metabox.find('.p2p-tab-search button');
|
200 |
+
$viewAll.click(function(){
|
201 |
+
searchTab.find_posts(1);
|
202 |
+
return false;
|
203 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
204 |
$searchInput = $metabox.find('.p2p-tab-search :text');
|
205 |
$searchInput.keypress(function(ev){
|
206 |
if (13 === ev.keyCode) {
|
214 |
return delayed = setTimeout(function(){
|
215 |
var searchStr;
|
216 |
searchStr = $searchInput.val();
|
217 |
+
if (searchStr === searchTab.params.s) {
|
218 |
return;
|
219 |
}
|
220 |
+
searchTab.params.s = searchStr;
|
221 |
$spinner.insertAfter($searchInput).show();
|
222 |
return searchTab.find_posts(1);
|
223 |
}, 400);
|
224 |
});
|
225 |
+
$createButton = $metabox.find('.p2p-tab-create-post button');
|
226 |
$createInput = $metabox.find('.p2p-tab-create-post :text');
|
227 |
$createButton.click(function(){
|
228 |
var $button, title, data;
|
admin/box.php
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
*/
|
6 |
interface P2P_Field {
|
7 |
function get_title();
|
8 |
-
function render( $
|
9 |
}
|
10 |
|
11 |
/**
|
@@ -20,20 +20,12 @@ class P2P_Box {
|
|
20 |
|
21 |
private $columns;
|
22 |
|
23 |
-
private static $extra_qv = array(
|
24 |
-
'update_post_term_cache' => false,
|
25 |
-
'update_post_meta_cache' => false,
|
26 |
-
'post_status' => 'any',
|
27 |
-
);
|
28 |
-
|
29 |
function __construct( $args, $ctype ) {
|
30 |
$this->args = $args;
|
31 |
|
32 |
$this->ctype = $ctype;
|
33 |
|
34 |
-
$this->
|
35 |
-
|
36 |
-
add_filter( 'posts_search', array( __CLASS__, '_search_by_title' ), 10, 2 );
|
37 |
|
38 |
$this->init_columns();
|
39 |
}
|
@@ -50,28 +42,33 @@ class P2P_Box {
|
|
50 |
}
|
51 |
|
52 |
protected function init_columns() {
|
|
|
|
|
53 |
$this->columns = array(
|
54 |
'delete' => new P2P_Field_Delete,
|
55 |
-
'title' => new
|
56 |
);
|
57 |
|
58 |
foreach ( $this->args->fields as $key => $data ) {
|
59 |
-
$this->columns[ $key ] = new P2P_Field_Generic( $data );
|
60 |
}
|
61 |
|
62 |
-
if (
|
63 |
-
$this->columns['order'] = new P2P_Field_Order( $
|
64 |
}
|
65 |
}
|
66 |
|
67 |
-
function
|
68 |
-
$
|
69 |
-
$qv['nopaging'] = true;
|
70 |
|
71 |
-
|
|
|
|
|
|
|
|
|
72 |
|
73 |
$data = array(
|
74 |
-
'
|
75 |
'attributes' => $this->render_data_attributes(),
|
76 |
'connections' => $this->render_connections_table( $post ),
|
77 |
'create-connections' => $this->render_create_connections( $post ),
|
@@ -82,7 +79,6 @@ class P2P_Box {
|
|
82 |
|
83 |
protected function render_data_attributes() {
|
84 |
$data_attr = array(
|
85 |
-
'ctype_id' => $this->ctype->id,
|
86 |
'prevent_duplicates' => $this->ctype->prevent_duplicates,
|
87 |
'cardinality' => $this->ctype->accepts_single_connection() ? 'one' : 'many',
|
88 |
'direction' => $this->ctype->get_direction()
|
@@ -98,12 +94,12 @@ class P2P_Box {
|
|
98 |
protected function render_connections_table( $post ) {
|
99 |
$data = array();
|
100 |
|
101 |
-
if ( empty( $this->
|
102 |
$data['hide'] = 'style="display:none"';
|
103 |
|
104 |
$tbody = array();
|
105 |
-
foreach ( $this->
|
106 |
-
$tbody[] = $this->connection_row( $
|
107 |
}
|
108 |
$data['tbody'] = $tbody;
|
109 |
|
@@ -122,12 +118,13 @@ class P2P_Box {
|
|
122 |
'label' => __( 'Create connections:', P2P_TEXTDOMAIN )
|
123 |
);
|
124 |
|
125 |
-
if ( $this->ctype->accepts_single_connection() && !empty( $this->
|
126 |
$data['hide'] = 'style="display:none"';
|
127 |
|
128 |
// Search tab
|
129 |
$tab_content = P2P_Mustache::render( 'tab-search', array(
|
130 |
-
'placeholder' => $this->
|
|
|
131 |
) );
|
132 |
|
133 |
$data['tabs'][] = array(
|
@@ -137,26 +134,21 @@ class P2P_Box {
|
|
137 |
'tab-content' => $tab_content
|
138 |
);
|
139 |
|
140 |
-
// List tab
|
141 |
-
$data['tabs'][] = array(
|
142 |
-
'tab-id' => 'list',
|
143 |
-
'tab-title' => __( 'View All', P2P_TEXTDOMAIN ),
|
144 |
-
'tab-content' => $this->post_rows( $post->ID )
|
145 |
-
);
|
146 |
-
|
147 |
// Create post tab
|
148 |
if ( $this->can_create_post() ) {
|
149 |
$tab_content = P2P_Mustache::render( 'tab-create-post', array(
|
150 |
-
'title' => $this->
|
151 |
) );
|
152 |
|
153 |
$data['tabs'][] = array(
|
154 |
'tab-id' => 'create-post',
|
155 |
-
'tab-title' => $this->
|
156 |
'tab-content' => $tab_content
|
157 |
);
|
158 |
}
|
159 |
|
|
|
|
|
160 |
return $data;
|
161 |
}
|
162 |
|
@@ -170,7 +162,7 @@ class P2P_Box {
|
|
170 |
foreach ( $columns as $key => $field ) {
|
171 |
$data['columns'][] = array(
|
172 |
'column' => $key,
|
173 |
-
'content' => $field->render( $
|
174 |
);
|
175 |
}
|
176 |
|
@@ -181,36 +173,20 @@ class P2P_Box {
|
|
181 |
}
|
182 |
|
183 |
protected function post_rows( $current_post_id, $page = 1, $search = '' ) {
|
184 |
-
$
|
185 |
-
'paged' => $page,
|
186 |
-
'posts_per_page' => 5,
|
187 |
-
) );
|
188 |
-
|
189 |
-
if ( $search ) {
|
190 |
-
$args['_p2p_box'] = true;
|
191 |
-
$args['s'] = $search;
|
192 |
-
}
|
193 |
-
|
194 |
-
$query = $this->ctype->get_connectable( $current_post_id, $args );
|
195 |
|
196 |
-
if ( empty( $
|
197 |
return false;
|
198 |
|
199 |
-
$candidate = (object) array(
|
200 |
-
'posts' => $query->posts,
|
201 |
-
'current_page' => max( 1, $query->get('paged') ),
|
202 |
-
'total_pages' => $query->max_num_pages
|
203 |
-
);
|
204 |
-
|
205 |
$data = array();
|
206 |
|
207 |
$columns = array(
|
208 |
'create' => new P2P_Field_Create,
|
209 |
-
'title' =>
|
210 |
);
|
211 |
|
212 |
-
foreach ( $candidate->
|
213 |
-
$data['rows'][] = $this->table_row( $columns, 0, $
|
214 |
}
|
215 |
|
216 |
if ( $candidate->total_pages > 1 ) {
|
@@ -243,7 +219,7 @@ class P2P_Box {
|
|
243 |
$args = array(
|
244 |
'post_title' => $_POST['post_title'],
|
245 |
'post_author' => get_current_user_id(),
|
246 |
-
'post_type' => $this->
|
247 |
);
|
248 |
|
249 |
$args = apply_filters( 'p2p_new_post_args', $args, $this->ctype );
|
@@ -265,63 +241,69 @@ class P2P_Box {
|
|
265 |
$p2p_id = $this->ctype->connect( $from, $to );
|
266 |
|
267 |
if ( $p2p_id )
|
268 |
-
|
|
|
|
|
269 |
|
270 |
-
die;
|
271 |
}
|
272 |
|
273 |
public function ajax_disconnect() {
|
274 |
-
|
275 |
|
276 |
-
|
277 |
}
|
278 |
|
279 |
public function ajax_clear_connections() {
|
280 |
$this->ctype->disconnect_all( $_POST['from'] );
|
281 |
|
282 |
-
|
283 |
}
|
284 |
|
285 |
public function ajax_search() {
|
286 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
287 |
|
288 |
if ( $rows ) {
|
289 |
$results = compact( 'rows' );
|
290 |
} else {
|
291 |
$results = array(
|
292 |
-
'msg' => $this->
|
293 |
);
|
294 |
}
|
295 |
|
296 |
-
|
297 |
}
|
298 |
|
299 |
protected function can_create_post() {
|
300 |
if ( !$this->args->can_create_post )
|
301 |
return false;
|
302 |
|
303 |
-
|
|
|
|
|
|
|
304 |
|
305 |
-
if ( count( $
|
306 |
return false;
|
307 |
|
308 |
-
if ( count( $
|
309 |
return false;
|
310 |
|
311 |
-
return
|
312 |
}
|
313 |
|
314 |
public function check_capability() {
|
315 |
-
return
|
316 |
-
}
|
317 |
-
|
318 |
-
function _search_by_title( $sql, $wp_query ) {
|
319 |
-
if ( $wp_query->is_search && $wp_query->get( '_p2p_box' ) ) {
|
320 |
-
list( $sql ) = explode( ' OR ', $sql, 2 );
|
321 |
-
return $sql . '))';
|
322 |
-
}
|
323 |
-
|
324 |
-
return $sql;
|
325 |
}
|
326 |
}
|
327 |
|
5 |
*/
|
6 |
interface P2P_Field {
|
7 |
function get_title();
|
8 |
+
function render( $p2p_id, $post_id );
|
9 |
}
|
10 |
|
11 |
/**
|
20 |
|
21 |
private $columns;
|
22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
function __construct( $args, $ctype ) {
|
24 |
$this->args = $args;
|
25 |
|
26 |
$this->ctype = $ctype;
|
27 |
|
28 |
+
$this->labels = $this->ctype->get_opposite( 'labels' );
|
|
|
|
|
29 |
|
30 |
$this->init_columns();
|
31 |
}
|
42 |
}
|
43 |
|
44 |
protected function init_columns() {
|
45 |
+
$title_class = $this->get_column_title_class();
|
46 |
+
|
47 |
$this->columns = array(
|
48 |
'delete' => new P2P_Field_Delete,
|
49 |
+
'title' => new $title_class( $this->labels->singular_name ),
|
50 |
);
|
51 |
|
52 |
foreach ( $this->args->fields as $key => $data ) {
|
53 |
+
$this->columns[ 'meta-' . $key ] = new P2P_Field_Generic( $key, $data );
|
54 |
}
|
55 |
|
56 |
+
if ( $orderby_key = $this->ctype->get_orderby_key() ) {
|
57 |
+
$this->columns['order'] = new P2P_Field_Order( $orderby_key );
|
58 |
}
|
59 |
}
|
60 |
|
61 |
+
protected function get_column_title_class() {
|
62 |
+
$object_type = $this->ctype->get_opposite( 'object' );
|
|
|
63 |
|
64 |
+
return 'P2P_Field_Title_' . ucfirst( $object_type );
|
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 ),
|
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()
|
94 |
protected function render_connections_table( $post ) {
|
95 |
$data = array();
|
96 |
|
97 |
+
if ( empty( $this->connected_items ) )
|
98 |
$data['hide'] = 'style="display:none"';
|
99 |
|
100 |
$tbody = array();
|
101 |
+
foreach ( $this->connected_items as $p2p_id => $item_id ) {
|
102 |
+
$tbody[] = $this->connection_row( $p2p_id, $item_id );
|
103 |
}
|
104 |
$data['tbody'] = $tbody;
|
105 |
|
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
|
125 |
$tab_content = P2P_Mustache::render( 'tab-search', array(
|
126 |
+
'placeholder' => $this->labels->search_items,
|
127 |
+
'view-all' => __( 'View All', P2P_TEXTDOMAIN ),
|
128 |
) );
|
129 |
|
130 |
$data['tabs'][] = array(
|
134 |
'tab-content' => $tab_content
|
135 |
);
|
136 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
// Create post tab
|
138 |
if ( $this->can_create_post() ) {
|
139 |
$tab_content = P2P_Mustache::render( 'tab-create-post', array(
|
140 |
+
'title' => $this->labels->add_new_item
|
141 |
) );
|
142 |
|
143 |
$data['tabs'][] = array(
|
144 |
'tab-id' => 'create-post',
|
145 |
+
'tab-title' => $this->labels->new_item,
|
146 |
'tab-content' => $tab_content
|
147 |
);
|
148 |
}
|
149 |
|
150 |
+
$data['show-tab-headers'] = count( $data['tabs'] ) > 1 ? array(true) : false;
|
151 |
+
|
152 |
return $data;
|
153 |
}
|
154 |
|
162 |
foreach ( $columns as $key => $field ) {
|
163 |
$data['columns'][] = array(
|
164 |
'column' => $key,
|
165 |
+
'content' => $field->render( $p2p_id, $post_id )
|
166 |
);
|
167 |
}
|
168 |
|
173 |
}
|
174 |
|
175 |
protected function post_rows( $current_post_id, $page = 1, $search = '' ) {
|
176 |
+
$candidate = $this->ctype->get_connectable( $current_post_id, $page, $search );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
|
178 |
+
if ( empty( $candidate->items ) )
|
179 |
return false;
|
180 |
|
|
|
|
|
|
|
|
|
|
|
|
|
181 |
$data = array();
|
182 |
|
183 |
$columns = array(
|
184 |
'create' => new P2P_Field_Create,
|
185 |
+
'title' => $this->columns['title']
|
186 |
);
|
187 |
|
188 |
+
foreach ( $candidate->items as $item ) {
|
189 |
+
$data['rows'][] = $this->table_row( $columns, 0, $item->ID );
|
190 |
}
|
191 |
|
192 |
if ( $candidate->total_pages > 1 ) {
|
219 |
$args = array(
|
220 |
'post_title' => $_POST['post_title'],
|
221 |
'post_author' => get_current_user_id(),
|
222 |
+
'post_type' => $this->ctype->get_opposite( 'side' )->post_type[0]
|
223 |
);
|
224 |
|
225 |
$args = apply_filters( 'p2p_new_post_args', $args, $this->ctype );
|
241 |
$p2p_id = $this->ctype->connect( $from, $to );
|
242 |
|
243 |
if ( $p2p_id )
|
244 |
+
$r = array( 'row' => $this->connection_row( $p2p_id, $to, true ) );
|
245 |
+
else
|
246 |
+
$r = array( 'error' => __( "Can't create connection.", P2P_TEXTDOMAIN ) );
|
247 |
|
248 |
+
die( json_encode( $r ) );
|
249 |
}
|
250 |
|
251 |
public function ajax_disconnect() {
|
252 |
+
p2p_delete_connection( $_POST['p2p_id'] );
|
253 |
|
254 |
+
$this->refresh_candidates();
|
255 |
}
|
256 |
|
257 |
public function ajax_clear_connections() {
|
258 |
$this->ctype->disconnect_all( $_POST['from'] );
|
259 |
|
260 |
+
$this->refresh_candidates();
|
261 |
}
|
262 |
|
263 |
public function ajax_search() {
|
264 |
+
die( json_encode( $this->_ajax_search( $_GET ) ) );
|
265 |
+
}
|
266 |
+
|
267 |
+
private function refresh_candidates() {
|
268 |
+
$results = $this->_ajax_search( $_POST );
|
269 |
+
|
270 |
+
die( json_encode( $results ) );
|
271 |
+
}
|
272 |
+
|
273 |
+
private function _ajax_search( $args ) {
|
274 |
+
$rows = $this->post_rows( $args['from'], $args['paged'], $args['s'] );
|
275 |
|
276 |
if ( $rows ) {
|
277 |
$results = compact( 'rows' );
|
278 |
} else {
|
279 |
$results = array(
|
280 |
+
'msg' => $this->labels->not_found,
|
281 |
);
|
282 |
}
|
283 |
|
284 |
+
return $results;
|
285 |
}
|
286 |
|
287 |
protected function can_create_post() {
|
288 |
if ( !$this->args->can_create_post )
|
289 |
return false;
|
290 |
|
291 |
+
if ( 'post' != $this->ctype->get_opposite( 'object' ) )
|
292 |
+
return false;
|
293 |
+
|
294 |
+
$side = $this->ctype->get_opposite( 'side' );
|
295 |
|
296 |
+
if ( count( $side->post_type ) > 1 )
|
297 |
return false;
|
298 |
|
299 |
+
if ( count( $side->query_vars ) > 1 )
|
300 |
return false;
|
301 |
|
302 |
+
return true;
|
303 |
}
|
304 |
|
305 |
public function check_capability() {
|
306 |
+
return $this->ctype->get_opposite( 'side' )->check_capability();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
307 |
}
|
308 |
}
|
309 |
|
admin/column-factory.php
CHANGED
@@ -4,14 +4,32 @@ class P2P_Column_Factory {
|
|
4 |
|
5 |
private static $column_args = array();
|
6 |
|
7 |
-
static function
|
8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
return false;
|
10 |
|
11 |
if ( !$column_args )
|
12 |
return false;
|
13 |
|
14 |
-
self::$column_args[$
|
15 |
|
16 |
return true;
|
17 |
}
|
@@ -24,8 +42,8 @@ class P2P_Column_Factory {
|
|
24 |
|
25 |
$post_type = $screen->post_type;
|
26 |
|
27 |
-
foreach ( self::$column_args as $
|
28 |
-
$ctype = p2p_type( $
|
29 |
|
30 |
$directed = $ctype->find_direction( $post_type );
|
31 |
if ( !$directed )
|
@@ -36,11 +54,13 @@ class P2P_Column_Factory {
|
|
36 |
|
37 |
$column = new P2P_Column( $directed );
|
38 |
|
|
|
|
|
39 |
add_filter( "manage_{$screen->id}_columns", array( $column, 'add_column' ) );
|
40 |
add_action( "manage_{$post_type}_posts_custom_column", array( $column, 'display_column' ), 10, 2 );
|
41 |
}
|
42 |
}
|
43 |
}
|
44 |
|
45 |
-
|
46 |
|
4 |
|
5 |
private static $column_args = array();
|
6 |
|
7 |
+
static function init() {
|
8 |
+
add_filter( 'p2p_connection_type_args', array( __CLASS__, 'filter_args' ) );
|
9 |
+
|
10 |
+
add_action( 'admin_print_styles', array( __CLASS__, 'add_columns' ) );
|
11 |
+
}
|
12 |
+
|
13 |
+
static function filter_args( $args ) {
|
14 |
+
if ( isset( $args['admin_column'] ) ) {
|
15 |
+
$column_args = _p2p_pluck( $args, 'admin_column' );
|
16 |
+
} else {
|
17 |
+
$column_args = false;
|
18 |
+
}
|
19 |
+
|
20 |
+
self::register( $args['name'], $column_args );
|
21 |
+
|
22 |
+
return $args;
|
23 |
+
}
|
24 |
+
|
25 |
+
static function register( $p2p_type, $column_args ) {
|
26 |
+
if ( isset( self::$column_args[$p2p_type] ) )
|
27 |
return false;
|
28 |
|
29 |
if ( !$column_args )
|
30 |
return false;
|
31 |
|
32 |
+
self::$column_args[$p2p_type] = $column_args;
|
33 |
|
34 |
return true;
|
35 |
}
|
42 |
|
43 |
$post_type = $screen->post_type;
|
44 |
|
45 |
+
foreach ( self::$column_args as $p2p_type => $column_args ) {
|
46 |
+
$ctype = p2p_type( $p2p_type );
|
47 |
|
48 |
$directed = $ctype->find_direction( $post_type );
|
49 |
if ( !$directed )
|
54 |
|
55 |
$column = new P2P_Column( $directed );
|
56 |
|
57 |
+
$column->styles();
|
58 |
+
|
59 |
add_filter( "manage_{$screen->id}_columns", array( $column, 'add_column' ) );
|
60 |
add_action( "manage_{$post_type}_posts_custom_column", array( $column, 'display_column' ), 10, 2 );
|
61 |
}
|
62 |
}
|
63 |
}
|
64 |
|
65 |
+
P2P_Column_Factory::init();
|
66 |
|
admin/column.php
CHANGED
@@ -15,26 +15,50 @@ class P2P_Column {
|
|
15 |
}
|
16 |
|
17 |
function add_column( $columns ) {
|
18 |
-
$columns[
|
19 |
|
20 |
return $columns;
|
21 |
}
|
22 |
|
23 |
-
function
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
return;
|
26 |
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
$args = array(
|
29 |
-
'
|
30 |
-
'
|
31 |
-
'
|
|
|
32 |
);
|
33 |
|
34 |
$url = add_query_arg( $args, admin_url( 'edit.php' ) );
|
35 |
|
36 |
-
echo html( 'li', html_link( $url, $
|
37 |
}
|
|
|
38 |
}
|
39 |
}
|
40 |
|
15 |
}
|
16 |
|
17 |
function add_column( $columns ) {
|
18 |
+
$columns[ $this->ctype->name ] = $this->ctype->get_current( 'title' );
|
19 |
|
20 |
return $columns;
|
21 |
}
|
22 |
|
23 |
+
function styles() {
|
24 |
+
?>
|
25 |
+
<style type="text/css">
|
26 |
+
.column-<?php echo $this->ctype->name; ?> ul {
|
27 |
+
margin-top: 0;
|
28 |
+
margin-bottom: 0;
|
29 |
+
}
|
30 |
+
</style>
|
31 |
+
<?php
|
32 |
+
}
|
33 |
+
|
34 |
+
function display_column( $column, $item_id ) {
|
35 |
+
if ( $this->ctype->name != $column )
|
36 |
return;
|
37 |
|
38 |
+
$opposite_direction = array(
|
39 |
+
'from' => 'to',
|
40 |
+
'to' => 'from',
|
41 |
+
'any' => 'any'
|
42 |
+
);
|
43 |
+
|
44 |
+
$direction = $opposite_direction[ $this->ctype->get_direction() ];
|
45 |
+
|
46 |
+
$side = $this->ctype->side[ $direction ];
|
47 |
+
|
48 |
+
echo '<ul>';
|
49 |
+
foreach ( $this->connected[ $item_id ] as $item ) {
|
50 |
$args = array(
|
51 |
+
'connected_type' => $this->ctype->name,
|
52 |
+
'connected_direction' => $direction,
|
53 |
+
'connected_items' => $item->ID,
|
54 |
+
'post_type' => get_current_screen()->post_type
|
55 |
);
|
56 |
|
57 |
$url = add_query_arg( $args, admin_url( 'edit.php' ) );
|
58 |
|
59 |
+
echo html( 'li', html_link( $url, $side->item_title( $item ) ) );
|
60 |
}
|
61 |
+
echo '</ul>';
|
62 |
}
|
63 |
}
|
64 |
|
admin/fields.php
CHANGED
@@ -1,8 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
/**
|
4 |
-
* @package Administration
|
5 |
-
*/
|
6 |
class P2P_Field_Create implements P2P_Field {
|
7 |
|
8 |
function get_title() {
|
@@ -10,7 +8,7 @@ class P2P_Field_Create implements P2P_Field {
|
|
10 |
return '';
|
11 |
}
|
12 |
|
13 |
-
function render( $
|
14 |
$data = array(
|
15 |
'post_id' => $post_id,
|
16 |
'title' => __( 'Create connection', P2P_TEXTDOMAIN )
|
@@ -20,9 +18,8 @@ class P2P_Field_Create implements P2P_Field {
|
|
20 |
}
|
21 |
}
|
22 |
|
23 |
-
|
24 |
-
|
25 |
-
*/
|
26 |
class P2P_Field_Delete implements P2P_Field {
|
27 |
|
28 |
function get_title() {
|
@@ -33,7 +30,7 @@ class P2P_Field_Delete implements P2P_Field {
|
|
33 |
return P2P_Mustache::render( 'column-delete-all', $data );
|
34 |
}
|
35 |
|
36 |
-
function render( $
|
37 |
$data = array(
|
38 |
'p2p_id' => $p2p_id,
|
39 |
'title' => __( 'Delete connection', P2P_TEXTDOMAIN )
|
@@ -43,9 +40,8 @@ class P2P_Field_Delete implements P2P_Field {
|
|
43 |
}
|
44 |
}
|
45 |
|
46 |
-
|
47 |
-
|
48 |
-
*/
|
49 |
class P2P_Field_Order implements P2P_Field {
|
50 |
|
51 |
protected $sort_key;
|
@@ -58,7 +54,7 @@ class P2P_Field_Order implements P2P_Field {
|
|
58 |
return '';
|
59 |
}
|
60 |
|
61 |
-
function render( $
|
62 |
return html( 'input', array(
|
63 |
'type' => 'hidden',
|
64 |
'name' => "p2p_order[$this->sort_key][]",
|
@@ -67,10 +63,37 @@ class P2P_Field_Order implements P2P_Field {
|
|
67 |
}
|
68 |
}
|
69 |
|
70 |
-
/**
|
71 |
-
|
72 |
-
|
73 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
|
75 |
protected $title;
|
76 |
|
@@ -82,7 +105,7 @@ class P2P_Field_Title implements P2P_Field {
|
|
82 |
return $this->title;
|
83 |
}
|
84 |
|
85 |
-
function render( $
|
86 |
$data = array(
|
87 |
'title-attr' => get_permalink( $post_id ),
|
88 |
'title' => get_post_field( 'post_title', $post_id ),
|
@@ -102,38 +125,45 @@ class P2P_Field_Title implements P2P_Field {
|
|
102 |
}
|
103 |
}
|
104 |
|
105 |
-
/**
|
106 |
-
* @package Administration
|
107 |
-
*/
|
108 |
-
class P2P_Field_Generic implements P2P_Field {
|
109 |
-
|
110 |
-
protected $data;
|
111 |
|
112 |
-
|
113 |
-
|
114 |
-
}
|
115 |
|
116 |
-
function
|
117 |
-
|
118 |
-
}
|
119 |
|
120 |
-
|
121 |
-
|
122 |
-
'
|
123 |
-
'
|
124 |
);
|
125 |
|
126 |
-
|
127 |
-
|
|
|
|
|
128 |
|
129 |
-
|
|
|
130 |
|
131 |
-
|
132 |
-
|
133 |
-
|
|
|
|
|
134 |
);
|
135 |
|
136 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
137 |
}
|
138 |
}
|
139 |
|
1 |
<?php
|
2 |
|
3 |
+
/** @package Administration */
|
|
|
|
|
4 |
class P2P_Field_Create implements P2P_Field {
|
5 |
|
6 |
function get_title() {
|
8 |
return '';
|
9 |
}
|
10 |
|
11 |
+
function render( $p2p_id, $post_id ) {
|
12 |
$data = array(
|
13 |
'post_id' => $post_id,
|
14 |
'title' => __( 'Create connection', P2P_TEXTDOMAIN )
|
18 |
}
|
19 |
}
|
20 |
|
21 |
+
|
22 |
+
/** @package Administration */
|
|
|
23 |
class P2P_Field_Delete implements P2P_Field {
|
24 |
|
25 |
function get_title() {
|
30 |
return P2P_Mustache::render( 'column-delete-all', $data );
|
31 |
}
|
32 |
|
33 |
+
function render( $p2p_id, $post_id ) {
|
34 |
$data = array(
|
35 |
'p2p_id' => $p2p_id,
|
36 |
'title' => __( 'Delete connection', P2P_TEXTDOMAIN )
|
40 |
}
|
41 |
}
|
42 |
|
43 |
+
|
44 |
+
/** @package Administration */
|
|
|
45 |
class P2P_Field_Order implements P2P_Field {
|
46 |
|
47 |
protected $sort_key;
|
54 |
return '';
|
55 |
}
|
56 |
|
57 |
+
function render( $p2p_id, $post_id ) {
|
58 |
return html( 'input', array(
|
59 |
'type' => 'hidden',
|
60 |
'name' => "p2p_order[$this->sort_key][]",
|
63 |
}
|
64 |
}
|
65 |
|
66 |
+
/** @package Administration */
|
67 |
+
class P2P_Field_Generic implements P2P_Field {
|
68 |
+
|
69 |
+
protected $key;
|
70 |
+
protected $data;
|
71 |
+
|
72 |
+
function __construct( $key, $data ) {
|
73 |
+
$this->key = $key;
|
74 |
+
$this->data = $data;
|
75 |
+
}
|
76 |
+
|
77 |
+
function get_title() {
|
78 |
+
return $this->data['title'];
|
79 |
+
}
|
80 |
+
|
81 |
+
function render( $p2p_id, $post_id ) {
|
82 |
+
$args = array(
|
83 |
+
'name' => array( 'p2p_meta', $p2p_id, $this->key ),
|
84 |
+
'type' => $this->data['type']
|
85 |
+
);
|
86 |
+
|
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;
|
99 |
|
105 |
return $this->title;
|
106 |
}
|
107 |
|
108 |
+
function render( $p2p_id, $post_id ) {
|
109 |
$data = array(
|
110 |
'title-attr' => get_permalink( $post_id ),
|
111 |
'title' => get_post_field( 'post_title', $post_id ),
|
125 |
}
|
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 ) {
|
133 |
+
list( $src ) = wp_get_attachment_image_src( $attachment_id, 'thumbnail', true );
|
|
|
134 |
|
135 |
+
$data = array(
|
136 |
+
'title-attr' => get_post_field( 'post_title', $attachment_id ),
|
137 |
+
'title' => html( 'img', compact( 'src' ) ),
|
138 |
+
'url' => get_edit_post_link( $attachment_id ),
|
139 |
);
|
140 |
|
141 |
+
return P2P_Mustache::render( 'column-title', $data );
|
142 |
+
}
|
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 ) {
|
150 |
+
$data = array(
|
151 |
+
'title-attr' => '',
|
152 |
+
'title' => get_user_by( 'id', $user_id )->display_name,
|
153 |
+
'url' => $this->get_edit_url( $user_id ),
|
154 |
);
|
155 |
|
156 |
+
return P2P_Mustache::render( 'column-title', $data );
|
157 |
+
}
|
158 |
+
|
159 |
+
private function get_edit_url( $user_id ) {
|
160 |
+
if ( get_current_user_id() == $user_id ) {
|
161 |
+
$edit_link = 'profile.php';
|
162 |
+
} else {
|
163 |
+
$edit_link = "user-edit.php?user_id=$user_id";
|
164 |
+
}
|
165 |
+
|
166 |
+
return admin_url( $edit_link );
|
167 |
}
|
168 |
}
|
169 |
|
admin/templates/box.html
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
-
<input type="hidden" name="p2p_ctypes[]" value="{{ctype-id}}" />
|
2 |
-
|
3 |
<div class="p2p-box" {{attributes}}>
|
|
|
|
|
4 |
{{#connections}}
|
5 |
<table class="p2p-connections" {{{hide}}}>
|
6 |
<thead>
|
@@ -21,12 +21,14 @@
|
|
21 |
|
22 |
{{#create-connections}}
|
23 |
<div class="p2p-create-connections" {{{hide}}}>
|
24 |
-
<p><strong>{{label}}</strong></p>
|
|
|
25 |
<ul class="wp-tab-bar clearfix">
|
26 |
{{#tabs}}
|
27 |
-
<li {{#is-active}}class="wp-tab-active"{{/is-active}} data-ref=".p2p-tab-{{tab-id}}"><a href="#">{{tab-title}}</a></li>
|
28 |
{{/tabs}}
|
29 |
</ul>
|
|
|
30 |
|
31 |
{{#tabs}}
|
32 |
<div class="p2p-tab-{{tab-id}} tabs-panel">
|
|
|
|
|
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>
|
21 |
|
22 |
{{#create-connections}}
|
23 |
<div class="p2p-create-connections" {{{hide}}}>
|
24 |
+
<p><strong>{{{label}}}</strong></p>
|
25 |
+
{{#show-tab-headers}}
|
26 |
<ul class="wp-tab-bar clearfix">
|
27 |
{{#tabs}}
|
28 |
+
<li {{#is-active}}class="wp-tab-active"{{/is-active}} data-ref=".p2p-tab-{{tab-id}}"><a href="#">{{{tab-title}}}</a></li>
|
29 |
{{/tabs}}
|
30 |
</ul>
|
31 |
+
{{/show-tab-headers}}
|
32 |
|
33 |
{{#tabs}}
|
34 |
<div class="p2p-tab-{{tab-id}} tabs-panel">
|
admin/templates/column-create.html
CHANGED
@@ -1 +1 @@
|
|
1 |
-
<a href="#" data-post_id="{{post_id}}" title="{{title}}"></a>
|
1 |
+
<a href="#" data-post_id="{{post_id}}" title="{{{title}}}"></a>
|
admin/templates/column-delete-all.html
CHANGED
@@ -1 +1 @@
|
|
1 |
-
<a href="#" title="{{title}}"></a>
|
1 |
+
<a href="#" title="{{{title}}}"></a>
|
admin/templates/column-delete.html
CHANGED
@@ -1 +1 @@
|
|
1 |
-
<a href="#" data-p2p_id="{{p2p_id}}" title="{{title}}"></a>
|
1 |
+
<a href="#" data-p2p_id="{{p2p_id}}" title="{{{title}}}"></a>
|
admin/templates/column-title.html
CHANGED
@@ -1 +1 @@
|
|
1 |
-
<a href="{{{url}}}" title="{{title-attr}}">{{title}}</a>{{#status}} - <span class="post-state">{{text}}</span>{{/status}}
|
1 |
+
<a href="{{{url}}}" title="{{title-attr}}">{{{title}}}</a>{{#status}} - <span class="post-state">{{text}}</span>{{/status}}
|
admin/templates/tab-create-post.html
CHANGED
@@ -1,2 +1,2 @@
|
|
1 |
<input type="text" name="p2p_new_title" autocomplete="off" />
|
2 |
-
<
|
1 |
<input type="text" name="p2p_new_title" autocomplete="off" />
|
2 |
+
<button class="button">{{{title}}}</button>
|
admin/templates/tab-search.html
CHANGED
@@ -1,3 +1,5 @@
|
|
1 |
<div class="p2p-search">
|
2 |
-
<input type="text" name="p2p_search" autocomplete="off" placeholder="{{placeholder}}" />
|
|
|
|
|
3 |
</div>
|
1 |
<div class="p2p-search">
|
2 |
+
<input type="text" name="p2p_search" autocomplete="off" placeholder="{{{placeholder}}}" />
|
3 |
+
|
4 |
+
<button class="button">{{{view-all}}}</button>
|
5 |
</div>
|
core/api.php
CHANGED
@@ -7,7 +7,7 @@
|
|
7 |
*
|
8 |
* Takes the following parameters, as an associative array:
|
9 |
*
|
10 |
-
* - '
|
11 |
*
|
12 |
* - 'from' - string|array The first end of the connection.
|
13 |
*
|
@@ -19,16 +19,20 @@
|
|
19 |
*
|
20 |
* - 'fields' - array( key => Title ) Metadata fields editable by the user. Default: none.
|
21 |
*
|
22 |
-
* - 'data' - array( key => value ) Metadata fields not editable by the user. Dfault: none.
|
23 |
-
*
|
24 |
* - 'cardinality' - string How many connection can each post have: 'one-to-many', 'many-to-one' or 'many-to-many'. Default: 'many-to-many'
|
25 |
*
|
26 |
* - 'prevent_duplicates' - bool Whether to disallow duplicate connections between the same two posts. Default: true.
|
27 |
*
|
|
|
|
|
28 |
* - 'sortable' - bool|string Whether to allow connections to be ordered via drag-and-drop. Can be 'from', 'to', 'any' or false. Default: false.
|
29 |
*
|
30 |
* - 'title' - string|array The box's title. Default: 'Connected {$post_type}s'
|
31 |
*
|
|
|
|
|
|
|
|
|
32 |
* - 'reciprocal' - bool For indeterminate connections: True means all connections are displayed in a single box. False means 'from' connections are shown in one box and 'to' connections are shown in another box. Default: false.
|
33 |
*
|
34 |
* - 'admin_box' - bool|string|array Whether and where to show the admin connections box.
|
@@ -46,109 +50,252 @@ function p2p_register_connection_type( $args ) {
|
|
46 |
|
47 |
$argv = func_get_args();
|
48 |
|
49 |
-
// Back-compat begin
|
50 |
if ( count( $argv ) > 1 ) {
|
51 |
$args = array();
|
52 |
foreach ( array( 'from', 'to', 'reciprocal' ) as $i => $key ) {
|
53 |
if ( isset( $argv[ $i ] ) )
|
54 |
$args[ $key ] = $argv[ $i ];
|
55 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
}
|
57 |
|
58 |
if ( isset( $args['show_ui'] ) ) {
|
59 |
$args['admin_box'] = array(
|
60 |
'show' => _p2p_pluck( $args, 'show_ui' )
|
61 |
);
|
|
|
62 |
if ( isset( $args['context'] ) )
|
63 |
$args['admin_box']['context'] = _p2p_pluck( $args, 'context' );
|
64 |
}
|
65 |
-
// Back-compat end
|
66 |
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
|
76 |
-
|
77 |
-
|
78 |
-
|
|
|
|
|
|
|
|
|
79 |
}
|
80 |
-
}
|
81 |
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
|
|
|
|
|
|
|
|
|
|
87 |
}
|
88 |
|
89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
|
91 |
-
|
92 |
-
|
93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
}
|
95 |
|
96 |
-
|
|
|
|
|
|
|
|
|
|
|
97 |
}
|
98 |
|
99 |
/**
|
100 |
-
*
|
|
|
|
|
|
|
|
|
101 |
*/
|
102 |
-
function
|
103 |
-
|
104 |
-
return $args['type'];
|
105 |
-
|
106 |
-
if ( isset( $args['values'] ) && is_array( $args['values'] ) )
|
107 |
-
return 'select';
|
108 |
|
109 |
-
return
|
110 |
}
|
111 |
|
112 |
/**
|
113 |
-
*
|
114 |
*
|
115 |
-
* @param
|
|
|
116 |
*
|
117 |
-
* @return bool|
|
118 |
*/
|
119 |
-
function
|
120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
}
|
122 |
|
123 |
/**
|
124 |
* Delete one or more connections.
|
125 |
*
|
126 |
-
* @param int
|
|
|
127 |
*
|
128 |
* @return int Number of connections deleted
|
129 |
*/
|
130 |
-
function
|
131 |
-
|
|
|
|
|
132 |
}
|
133 |
|
134 |
/**
|
135 |
-
*
|
136 |
*
|
137 |
-
* @param
|
138 |
-
*
|
|
|
139 |
*/
|
140 |
-
function
|
141 |
-
|
142 |
-
$posts = $posts->posts;
|
143 |
|
144 |
-
|
|
|
145 |
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
|
151 |
-
|
|
|
152 |
}
|
153 |
|
154 |
/**
|
7 |
*
|
8 |
* Takes the following parameters, as an associative array:
|
9 |
*
|
10 |
+
* - 'name' - string A unique identifier for this connection type.
|
11 |
*
|
12 |
* - 'from' - string|array The first end of the connection.
|
13 |
*
|
19 |
*
|
20 |
* - 'fields' - array( key => Title ) Metadata fields editable by the user. Default: none.
|
21 |
*
|
|
|
|
|
22 |
* - 'cardinality' - string How many connection can each post have: 'one-to-many', 'many-to-one' or 'many-to-many'. Default: 'many-to-many'
|
23 |
*
|
24 |
* - 'prevent_duplicates' - bool Whether to disallow duplicate connections between the same two posts. Default: true.
|
25 |
*
|
26 |
+
* - 'self_connections' - bool Whether to allow a post to connect to itself. Default: false.
|
27 |
+
*
|
28 |
* - 'sortable' - bool|string Whether to allow connections to be ordered via drag-and-drop. Can be 'from', 'to', 'any' or false. Default: false.
|
29 |
*
|
30 |
* - 'title' - string|array The box's title. Default: 'Connected {$post_type}s'
|
31 |
*
|
32 |
+
* - 'from_labels' - array Additional labels for the admin box (optional)
|
33 |
+
*
|
34 |
+
* - 'to_labels' - array Additional labels for the admin box (optional)
|
35 |
+
*
|
36 |
* - 'reciprocal' - bool For indeterminate connections: True means all connections are displayed in a single box. False means 'from' connections are shown in one box and 'to' connections are shown in another box. Default: false.
|
37 |
*
|
38 |
* - 'admin_box' - bool|string|array Whether and where to show the admin connections box.
|
50 |
|
51 |
$argv = func_get_args();
|
52 |
|
|
|
53 |
if ( count( $argv ) > 1 ) {
|
54 |
$args = array();
|
55 |
foreach ( array( 'from', 'to', 'reciprocal' ) as $i => $key ) {
|
56 |
if ( isset( $argv[ $i ] ) )
|
57 |
$args[ $key ] = $argv[ $i ];
|
58 |
}
|
59 |
+
} else {
|
60 |
+
$args = $argv[0];
|
61 |
+
}
|
62 |
+
|
63 |
+
if ( isset( $args['id'] ) ) {
|
64 |
+
$args['name'] = _p2p_pluck( $args, 'id' );
|
65 |
}
|
66 |
|
67 |
if ( isset( $args['show_ui'] ) ) {
|
68 |
$args['admin_box'] = array(
|
69 |
'show' => _p2p_pluck( $args, 'show_ui' )
|
70 |
);
|
71 |
+
|
72 |
if ( isset( $args['context'] ) )
|
73 |
$args['admin_box']['context'] = _p2p_pluck( $args, 'context' );
|
74 |
}
|
|
|
75 |
|
76 |
+
return P2P_Connection_Type_Factory::register( $args );
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Get a connection type.
|
81 |
+
*
|
82 |
+
* @param string $p2p_type
|
83 |
+
*
|
84 |
+
* @return bool|object False if connection type not found, P2P_Connection_Type instance on success.
|
85 |
+
*/
|
86 |
+
function p2p_type( $p2p_type ) {
|
87 |
+
return P2P_Connection_Type_Factory::get_instance( $p2p_type );
|
88 |
+
}
|
89 |
+
|
90 |
+
/**
|
91 |
+
* Check if a certain connection exists.
|
92 |
+
*
|
93 |
+
* @param string $p2p_type A valid connection type.
|
94 |
+
* @param array $args Query args.
|
95 |
+
*
|
96 |
+
* @return bool
|
97 |
+
*/
|
98 |
+
function p2p_connection_exists( $p2p_type, $args = array() ) {
|
99 |
+
$args['fields'] = 'count';
|
100 |
+
|
101 |
+
$r = p2p_get_connections( $p2p_type, $args );
|
102 |
+
|
103 |
+
return (bool) $r;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Retrieve connections.
|
108 |
+
*
|
109 |
+
* @param string $p2p_type A valid connection type.
|
110 |
+
* @param array $args Query args:
|
111 |
+
*
|
112 |
+
* - 'direction': Can be 'from', 'to' or 'any'
|
113 |
+
* - 'from': Object id. The first end of the connection. (optional)
|
114 |
+
* - 'to': Object id. The second end of the connection. (optional)
|
115 |
+
* - 'fields': Which field of the connection to return. Can be:
|
116 |
+
* 'all', 'object_id', 'p2p_from', 'p2p_to', 'p2p_id' or 'count'
|
117 |
+
*
|
118 |
+
* @return array
|
119 |
+
*/
|
120 |
+
function p2p_get_connections( $p2p_type, $args = array() ) {
|
121 |
+
extract( wp_parse_args( $args, array(
|
122 |
+
'direction' => 'from',
|
123 |
+
'from' => 'any',
|
124 |
+
'to' => 'any',
|
125 |
+
'fields' => 'all',
|
126 |
+
) ), EXTR_SKIP );
|
127 |
|
128 |
+
$r = array();
|
129 |
+
|
130 |
+
foreach ( _p2p_expand_direction( $direction ) as $direction ) {
|
131 |
+
$args = array( $from, $to );
|
132 |
+
|
133 |
+
if ( 'to' == $direction ) {
|
134 |
+
$args = array_reverse( $args );
|
135 |
}
|
|
|
136 |
|
137 |
+
if ( 'object_id' == $fields )
|
138 |
+
$field = ( 'to' == $direction ) ? 'p2p_from' : 'p2p_to';
|
139 |
+
else
|
140 |
+
$field = $fields;
|
141 |
+
|
142 |
+
$r = array_merge( $r, _p2p_get_connections( $p2p_type, array(
|
143 |
+
'from' => $args[0],
|
144 |
+
'to' => $args[1],
|
145 |
+
'fields' => $field
|
146 |
+
) ) );
|
147 |
}
|
148 |
|
149 |
+
if ( 'count' == $fields )
|
150 |
+
return array_sum( $r );
|
151 |
+
|
152 |
+
return $r;
|
153 |
+
}
|
154 |
+
|
155 |
+
/** @internal */
|
156 |
+
function _p2p_get_connections( $p2p_type, $args = array() ) {
|
157 |
+
global $wpdb;
|
158 |
+
|
159 |
+
extract( $args, EXTR_SKIP );
|
160 |
|
161 |
+
$where = $wpdb->prepare( 'WHERE p2p_type = %s', $p2p_type );
|
162 |
+
|
163 |
+
foreach ( array( 'from', 'to' ) as $key ) {
|
164 |
+
if ( 'any' == $$key )
|
165 |
+
continue;
|
166 |
+
|
167 |
+
$where .= $wpdb->prepare( " AND p2p_$key = %d", $$key );
|
168 |
+
}
|
169 |
+
|
170 |
+
switch ( $fields ) {
|
171 |
+
case 'p2p_id':
|
172 |
+
case 'p2p_from':
|
173 |
+
case 'p2p_to':
|
174 |
+
$sql_field = $fields;
|
175 |
+
break;
|
176 |
+
case 'count':
|
177 |
+
$sql_field = 'COUNT(*)';
|
178 |
+
break;
|
179 |
+
default:
|
180 |
+
$sql_field = '*';
|
181 |
}
|
182 |
|
183 |
+
$query = "SELECT $sql_field FROM $wpdb->p2p $where";
|
184 |
+
|
185 |
+
if ( '*' == $sql_field )
|
186 |
+
return $wpdb->get_results( $query );
|
187 |
+
else
|
188 |
+
return $wpdb->get_col( $query );
|
189 |
}
|
190 |
|
191 |
/**
|
192 |
+
* Retrieve a single connection.
|
193 |
+
*
|
194 |
+
* @param int $p2p_id The connection id.
|
195 |
+
*
|
196 |
+
* @return object
|
197 |
*/
|
198 |
+
function p2p_get_connection( $p2p_id ) {
|
199 |
+
global $wpdb;
|
|
|
|
|
|
|
|
|
200 |
|
201 |
+
return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->p2p WHERE p2p_id = %d", $p2p_id ) );
|
202 |
}
|
203 |
|
204 |
/**
|
205 |
+
* Create a connection.
|
206 |
*
|
207 |
+
* @param int $p2p_type A valid connection type.
|
208 |
+
* @param array $args Connection information.
|
209 |
*
|
210 |
+
* @return bool|int False on failure, p2p_id on success.
|
211 |
*/
|
212 |
+
function p2p_create_connection( $p2p_type, $args ) {
|
213 |
+
global $wpdb;
|
214 |
+
|
215 |
+
extract( wp_parse_args( $args, array(
|
216 |
+
'direction' => 'from',
|
217 |
+
'from' => false,
|
218 |
+
'to' => false,
|
219 |
+
'meta' => array()
|
220 |
+
) ), EXTR_SKIP );
|
221 |
+
|
222 |
+
$from = absint( $from );
|
223 |
+
$to = absint( $to );
|
224 |
+
|
225 |
+
if ( !$from || !$to )
|
226 |
+
return false;
|
227 |
+
|
228 |
+
$args = array( $from, $to );
|
229 |
+
|
230 |
+
if ( 'to' == $direction ) {
|
231 |
+
$args = array_reverse( $args );
|
232 |
+
}
|
233 |
+
|
234 |
+
$wpdb->insert( $wpdb->p2p, array(
|
235 |
+
'p2p_type' => $p2p_type,
|
236 |
+
'p2p_from' => $args[0],
|
237 |
+
'p2p_to' => $args[1]
|
238 |
+
) );
|
239 |
+
|
240 |
+
$p2p_id = $wpdb->insert_id;
|
241 |
+
|
242 |
+
foreach ( $meta as $key => $value )
|
243 |
+
p2p_add_meta( $p2p_id, $key, $value );
|
244 |
+
|
245 |
+
return $p2p_id;
|
246 |
}
|
247 |
|
248 |
/**
|
249 |
* Delete one or more connections.
|
250 |
*
|
251 |
+
* @param int $p2p_type A valid connection type.
|
252 |
+
* @param array $args Connection information.
|
253 |
*
|
254 |
* @return int Number of connections deleted
|
255 |
*/
|
256 |
+
function p2p_delete_connections( $p2p_type, $args = array() ) {
|
257 |
+
$args['fields'] = 'p2p_id';
|
258 |
+
|
259 |
+
return p2p_delete_connection( p2p_get_connections( $p2p_type, $args ) );
|
260 |
}
|
261 |
|
262 |
/**
|
263 |
+
* Delete connections using p2p_ids.
|
264 |
*
|
265 |
+
* @param int|array $p2p_id Connection ids
|
266 |
+
*
|
267 |
+
* @return int Number of connections deleted
|
268 |
*/
|
269 |
+
function p2p_delete_connection( $p2p_id ) {
|
270 |
+
global $wpdb;
|
|
|
271 |
|
272 |
+
if ( empty( $p2p_id ) )
|
273 |
+
return 0;
|
274 |
|
275 |
+
$p2p_ids = array_map( 'absint', (array) $p2p_id );
|
276 |
+
|
277 |
+
$where = "WHERE p2p_id IN (" . implode( ',', $p2p_ids ) . ")";
|
278 |
+
|
279 |
+
$count = $wpdb->query( "DELETE FROM $wpdb->p2p $where" );
|
280 |
+
$wpdb->query( "DELETE FROM $wpdb->p2pmeta $where" );
|
281 |
+
|
282 |
+
return $count;
|
283 |
+
}
|
284 |
+
|
285 |
+
function p2p_get_meta( $p2p_id, $key = '', $single = false ) {
|
286 |
+
return get_metadata( 'p2p', $p2p_id, $key, $single );
|
287 |
+
}
|
288 |
+
|
289 |
+
function p2p_update_meta( $p2p_id, $key, $value, $prev_value = '' ) {
|
290 |
+
return update_metadata( 'p2p', $p2p_id, $key, $value, $prev_value );
|
291 |
+
}
|
292 |
+
|
293 |
+
function p2p_add_meta( $p2p_id, $key, $value, $unique = false ) {
|
294 |
+
return add_metadata( 'p2p', $p2p_id, $key, $value, $unique );
|
295 |
+
}
|
296 |
|
297 |
+
function p2p_delete_meta( $p2p_id, $key, $value = '' ) {
|
298 |
+
return delete_metadata( 'p2p', $p2p_id, $key, $value );
|
299 |
}
|
300 |
|
301 |
/**
|
core/directed-type.php
CHANGED
@@ -5,24 +5,9 @@ class P2P_Directed_Connection_Type {
|
|
5 |
protected $ctype;
|
6 |
protected $direction;
|
7 |
|
8 |
-
protected $cardinality;
|
9 |
-
protected $other_cardinality;
|
10 |
-
|
11 |
function __construct( $ctype, $direction ) {
|
12 |
$this->ctype = $ctype;
|
13 |
$this->direction = $direction;
|
14 |
-
|
15 |
-
$this->set_cardinality();
|
16 |
-
}
|
17 |
-
|
18 |
-
protected function set_cardinality() {
|
19 |
-
$parts = explode( '-', $this->ctype->cardinality );
|
20 |
-
|
21 |
-
if ( 'to' == $this->direction )
|
22 |
-
$parts = array_reverse( $parts );
|
23 |
-
|
24 |
-
$this->cardinality = ( 'one' == $parts[2] ) ? 'one' : 'many';
|
25 |
-
$this->other_cardinality = ( 'one' == $parts[0] ) ? 'one' : 'many';
|
26 |
}
|
27 |
|
28 |
function __get( $key ) {
|
@@ -45,31 +30,26 @@ class P2P_Directed_Connection_Type {
|
|
45 |
return $this->ctype;
|
46 |
}
|
47 |
|
48 |
-
public function
|
49 |
-
|
|
|
|
|
50 |
}
|
51 |
|
52 |
-
public function
|
53 |
-
$
|
54 |
|
55 |
-
return $this->
|
56 |
}
|
57 |
|
58 |
-
|
59 |
-
|
60 |
-
}
|
61 |
|
62 |
-
|
63 |
-
return 'to' == $this->direction ? $this->from : $this->to;
|
64 |
}
|
65 |
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
return array_merge( $base_qv, array(
|
70 |
-
'suppress_filters' => false,
|
71 |
-
'ignore_sticky_posts' => true,
|
72 |
-
) );
|
73 |
}
|
74 |
|
75 |
/**
|
@@ -78,103 +58,137 @@ class P2P_Directed_Connection_Type {
|
|
78 |
* @param int|array $post_id A post id or an array of post ids.
|
79 |
* @param array $extra_qv Additional query variables to use.
|
80 |
*
|
81 |
-
* @return
|
82 |
*/
|
83 |
-
public function get_connected( $post_id, $extra_qv = array() ) {
|
84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
}
|
86 |
|
87 |
-
public function get_connected_args( $
|
88 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
|
90 |
-
|
91 |
-
|
|
|
|
|
|
|
92 |
'connected_meta' => $this->data
|
93 |
) );
|
94 |
|
95 |
-
$
|
96 |
-
|
97 |
-
|
98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
|
100 |
-
return
|
101 |
}
|
102 |
|
103 |
/**
|
104 |
* Get a list of posts that could be connected to a given post.
|
105 |
*
|
106 |
* @param int $post_id A post id.
|
107 |
-
* @param array $extra_qv Additional query variables to use.
|
108 |
-
*
|
109 |
-
* @return bool|object False on failure; A WP_Query instance on success.
|
110 |
*/
|
111 |
-
public function get_connectable( $
|
112 |
-
$
|
113 |
|
114 |
-
if (
|
115 |
-
$
|
116 |
-
} elseif ( $this->prevent_duplicates ) {
|
117 |
-
$to_check = $post_id;
|
118 |
-
}
|
119 |
|
120 |
-
if (
|
121 |
-
$
|
|
|
|
|
|
|
|
|
122 |
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
|
|
128 |
}
|
129 |
|
130 |
-
$
|
131 |
|
132 |
-
|
133 |
-
}
|
134 |
|
135 |
-
|
136 |
-
$connected = $this->get_connected( $from, array( 'post__in' => array( $to ) ) );
|
137 |
-
|
138 |
-
if ( !empty( $connected->posts ) )
|
139 |
-
return (int) $connected->posts[0]->p2p_id;
|
140 |
|
141 |
-
return
|
142 |
}
|
143 |
|
144 |
/**
|
145 |
-
* Connect two
|
146 |
*
|
147 |
* @param int The first end of the connection.
|
148 |
* @param int The second end of the connection.
|
|
|
149 |
*
|
150 |
* @return int p2p_id
|
151 |
*/
|
152 |
-
public function connect( $from, $to ) {
|
153 |
-
if (
|
154 |
return false;
|
155 |
|
156 |
-
$
|
157 |
-
|
158 |
-
if ( 'one' == $this->cardinality ) {
|
159 |
-
$connected = $this->get_connected( $from, array( 'fields' => 'ids' ) );
|
160 |
-
if ( !empty( $connected->posts ) )
|
161 |
-
return false;
|
162 |
-
}
|
163 |
-
|
164 |
-
if ( $this->prevent_duplicates ) {
|
165 |
-
$p2p_id = $this->get_p2p_id( $from, $to );
|
166 |
-
}
|
167 |
-
|
168 |
-
if ( !$p2p_id ) {
|
169 |
-
$args = array( $from, $to );
|
170 |
-
|
171 |
-
if ( 'to' == $this->direction )
|
172 |
-
$args = array_reverse( $args );
|
173 |
|
174 |
-
|
175 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
176 |
|
177 |
-
return $
|
|
|
|
|
|
|
|
|
|
|
178 |
}
|
179 |
|
180 |
/**
|
@@ -184,7 +198,11 @@ class P2P_Directed_Connection_Type {
|
|
184 |
* @param int The second end of the connection.
|
185 |
*/
|
186 |
public function disconnect( $from, $to ) {
|
187 |
-
return
|
|
|
|
|
|
|
|
|
188 |
}
|
189 |
|
190 |
/**
|
@@ -193,10 +211,47 @@ class P2P_Directed_Connection_Type {
|
|
193 |
* @param int The post id.
|
194 |
*/
|
195 |
public function disconnect_all( $from ) {
|
196 |
-
|
|
|
|
|
|
|
|
|
197 |
|
198 |
-
|
199 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
}
|
201 |
}
|
202 |
|
5 |
protected $ctype;
|
6 |
protected $direction;
|
7 |
|
|
|
|
|
|
|
8 |
function __construct( $ctype, $direction ) {
|
9 |
$this->ctype = $ctype;
|
10 |
$this->direction = $direction;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
}
|
12 |
|
13 |
function __get( $key ) {
|
30 |
return $this->ctype;
|
31 |
}
|
32 |
|
33 |
+
public function get_opposite( $key ) {
|
34 |
+
$direction = ( 'to' == $this->direction ) ? 'from' : 'to';
|
35 |
+
|
36 |
+
return $this->get_arg( $key, $direction );
|
37 |
}
|
38 |
|
39 |
+
public function get_current( $key ) {
|
40 |
+
$direction = ( 'to' == $this->direction ) ? 'to' : 'from';
|
41 |
|
42 |
+
return $this->get_arg( $key, $direction );
|
43 |
}
|
44 |
|
45 |
+
private function get_arg( $key, $direction ) {
|
46 |
+
$arg = $this->ctype->$key;
|
|
|
47 |
|
48 |
+
return $arg[$direction];
|
|
|
49 |
}
|
50 |
|
51 |
+
public function accepts_single_connection() {
|
52 |
+
return 'one' == $this->get_opposite( 'cardinality' );
|
|
|
|
|
|
|
|
|
|
|
53 |
}
|
54 |
|
55 |
/**
|
58 |
* @param int|array $post_id A post id or an array of post ids.
|
59 |
* @param array $extra_qv Additional query variables to use.
|
60 |
*
|
61 |
+
* @return object
|
62 |
*/
|
63 |
+
public function get_connected( $post_id, $extra_qv = array(), $output = 'raw' ) {
|
64 |
+
$args = array_merge( $extra_qv, array(
|
65 |
+
'connected_items' => $post_id
|
66 |
+
) );
|
67 |
+
|
68 |
+
$side = $this->get_opposite( 'side' );
|
69 |
+
|
70 |
+
$query = $side->do_query( $this->get_connected_args( $args ) );
|
71 |
+
|
72 |
+
if ( 'abstract' == $output )
|
73 |
+
$query = $side->abstract_query( $query );
|
74 |
+
|
75 |
+
return $query;
|
76 |
}
|
77 |
|
78 |
+
public function get_connected_args( $q ) {
|
79 |
+
if ( $orderby_key = $this->get_orderby_key() ) {
|
80 |
+
$q = wp_parse_args( $q, array(
|
81 |
+
'connected_orderby' => $orderby_key,
|
82 |
+
'connected_order' => 'ASC',
|
83 |
+
'connected_order_num' => true,
|
84 |
+
) );
|
85 |
+
}
|
86 |
|
87 |
+
$q = array_merge( $this->get_opposite( 'side' )->get_base_qv(), $q, array(
|
88 |
+
'p2p_type' => array( $this->name => $this->get_direction() ),
|
89 |
+
) );
|
90 |
+
|
91 |
+
$q = array_merge_recursive( $q, array(
|
92 |
'connected_meta' => $this->data
|
93 |
) );
|
94 |
|
95 |
+
return apply_filters( 'p2p_connected_args', $q, $this, $q['connected_items'] );
|
96 |
+
}
|
97 |
+
|
98 |
+
public function get_orderby_key() {
|
99 |
+
if ( !$this->sortable || 'any' == $this->direction )
|
100 |
+
return false;
|
101 |
+
|
102 |
+
if ( 'any' == $this->sortable || $this->direction == $this->sortable )
|
103 |
+
return '_order_' . $this->direction;
|
104 |
+
|
105 |
+
// Back-compat
|
106 |
+
if ( 'from' == $this->direction )
|
107 |
+
return $this->sortable;
|
108 |
+
|
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 |
/**
|
157 |
+
* Connect two items.
|
158 |
*
|
159 |
* @param int The first end of the connection.
|
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 )
|
191 |
+
) );
|
192 |
}
|
193 |
|
194 |
/**
|
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 |
* @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 |
|
core/ordered-type.php
DELETED
@@ -1,27 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class P2P_Ordered_Connection_Type extends P2P_Directed_Connection_Type {
|
4 |
-
|
5 |
-
protected $orderby_key;
|
6 |
-
|
7 |
-
function __construct( $ctype, $direction, $orderby_key ) {
|
8 |
-
$this->orderby_key = $orderby_key;
|
9 |
-
|
10 |
-
parent::__construct( $ctype, $direction );
|
11 |
-
}
|
12 |
-
|
13 |
-
public function get_orderby_key() {
|
14 |
-
return $this->orderby_key;
|
15 |
-
}
|
16 |
-
|
17 |
-
public function get_connected( $post_id, $extra_qv = array() ) {
|
18 |
-
$extra_qv = wp_parse_args( $extra_qv, array(
|
19 |
-
'connected_orderby' => $this->get_orderby_key(),
|
20 |
-
'connected_order' => 'ASC',
|
21 |
-
'connected_order_num' => true,
|
22 |
-
) );
|
23 |
-
|
24 |
-
return parent::get_connected( $post_id, $extra_qv );
|
25 |
-
}
|
26 |
-
}
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/query-post.php
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Handles connected{_to|_from} query vars
|
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' );
|
32 |
+
|
33 |
+
if ( false === $r ) {
|
34 |
+
$q = array( 'year' => 2525 );
|
35 |
+
} elseif ( $r ) {
|
36 |
+
$wp_query->is_home = false;
|
37 |
+
$wp_query->is_archive = true;
|
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;
|
50 |
+
|
51 |
+
return P2P_Query::alter_clauses( $clauses, $qv, "$wpdb->posts.ID" );
|
52 |
+
}
|
53 |
+
|
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 |
+
|
61 |
+
if ( isset( $wp_query->_p2p_cache ) ) {
|
62 |
+
update_meta_cache( 'p2p', wp_list_pluck( $the_posts, 'p2p_id' ) );
|
63 |
+
}
|
64 |
+
|
65 |
+
return $the_posts;
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
P2P_WP_Query::init();
|
70 |
+
|
core/query-user.php
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
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";
|
23 |
+
return;
|
24 |
+
}
|
25 |
+
|
26 |
+
// alter query
|
27 |
+
|
28 |
+
$qv = P2P_Query::get_qv( $q );
|
29 |
+
|
30 |
+
if ( empty( $qv['items'] ) )
|
31 |
+
return;
|
32 |
+
|
33 |
+
$map = array(
|
34 |
+
'fields' => 'query_fields',
|
35 |
+
'join' => 'query_from',
|
36 |
+
'where' => 'query_where',
|
37 |
+
'orderby' => 'query_orderby',
|
38 |
+
);
|
39 |
+
|
40 |
+
$clauses = array();
|
41 |
+
|
42 |
+
foreach ( $map as $clause => $key )
|
43 |
+
$clauses[$clause] = $query->$key;
|
44 |
+
|
45 |
+
$clauses = P2P_Query::alter_clauses( $clauses, $qv, "$wpdb->users.ID" );
|
46 |
+
|
47 |
+
if ( 0 !== strpos( $clauses['orderby'], 'ORDER BY ' ) )
|
48 |
+
$clauses['orderby'] = 'ORDER BY ' . $clauses['orderby'];
|
49 |
+
|
50 |
+
foreach ( $map as $clause => $key )
|
51 |
+
$query->$key = $clauses[$clause];
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
P2P_User_Query::init();
|
56 |
+
|
core/query.php
CHANGED
@@ -1,17 +1,8 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
/**
|
4 |
-
* Handles connected{_to|_from} query vars
|
5 |
-
*/
|
6 |
class P2P_Query {
|
7 |
|
8 |
-
function
|
9 |
-
add_action( 'parse_query', array( __CLASS__, 'parse_legacy_qv' ) );
|
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_legacy_qv( $wp_query ) {
|
15 |
$qv_map = array(
|
16 |
'connected' => 'any',
|
17 |
'connected_to' => 'to',
|
@@ -19,116 +10,182 @@ class P2P_Query {
|
|
19 |
);
|
20 |
|
21 |
foreach ( $qv_map as $key => $direction ) {
|
22 |
-
|
23 |
-
|
24 |
-
$
|
25 |
-
'posts' => $search,
|
26 |
-
'direction' => $direction,
|
27 |
-
) );
|
28 |
-
|
29 |
-
$wp_query->set( $key, false );
|
30 |
}
|
31 |
}
|
32 |
}
|
33 |
|
34 |
-
function
|
35 |
-
|
|
|
|
|
|
|
36 |
|
37 |
-
$
|
38 |
-
|
39 |
-
return $clauses;
|
40 |
}
|
41 |
|
42 |
-
$
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
-
$
|
49 |
|
50 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
|
52 |
$clauses['fields'] .= ", $wpdb->p2p.*";
|
53 |
|
54 |
$clauses['join'] .= " INNER JOIN $wpdb->p2p";
|
55 |
|
56 |
-
|
|
|
57 |
$search = false;
|
58 |
} else {
|
59 |
-
$search = implode( ',', array_map( 'absint', (array) $
|
60 |
}
|
61 |
|
62 |
-
$
|
63 |
-
|
64 |
-
|
|
|
|
|
|
|
|
|
65 |
|
66 |
-
if ( 'any' == $direction ) {
|
67 |
-
if ( $search ) {
|
68 |
-
$clauses['where'] .= " AND (
|
69 |
-
($wpdb->posts.ID = $wpdb->p2p.p2p_to AND $wpdb->p2p.p2p_from IN ($search)) OR
|
70 |
-
($wpdb->posts.ID = $wpdb->p2p.p2p_from AND $wpdb->p2p.p2p_to IN ($search))
|
71 |
-
)";
|
72 |
-
} else {
|
73 |
-
$clauses['where'] .= " AND ($wpdb->posts.ID = $wpdb->p2p.p2p_to OR $wpdb->posts.ID = $wpdb->p2p.p2p_from)";
|
74 |
-
}
|
75 |
-
} else {
|
76 |
$fields = array( 'p2p_from', 'p2p_to' );
|
77 |
-
if ( 'from' == $direction )
|
78 |
-
$fields = array_reverse( $fields );
|
79 |
|
80 |
-
|
81 |
|
82 |
-
|
83 |
-
|
84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
}
|
|
|
|
|
86 |
}
|
87 |
|
88 |
-
|
89 |
-
|
90 |
-
|
|
|
|
|
|
|
|
|
|
|
91 |
foreach ( $meta_clauses as $key => $value ) {
|
92 |
$clauses[ $key ] .= $value;
|
93 |
}
|
94 |
}
|
95 |
|
96 |
// Handle ordering
|
97 |
-
|
98 |
-
if ( $connected_orderby ) {
|
99 |
$clauses['join'] .= $wpdb->prepare( "
|
100 |
LEFT JOIN $wpdb->p2pmeta AS p2pm_order ON (
|
101 |
$wpdb->p2p.p2p_id = p2pm_order.p2p_id AND p2pm_order.meta_key = %s
|
102 |
)
|
103 |
-
", $
|
104 |
|
105 |
-
$
|
106 |
|
107 |
$field = 'meta_value';
|
108 |
|
109 |
-
if ( $
|
110 |
$field .= '+0';
|
111 |
|
112 |
-
$clauses['orderby'] = "p2pm_order.$field $
|
113 |
}
|
114 |
|
115 |
return $clauses;
|
116 |
}
|
117 |
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
return $the_posts;
|
124 |
|
125 |
-
if (
|
126 |
-
|
127 |
-
}
|
128 |
|
129 |
-
return $
|
130 |
}
|
131 |
-
}
|
132 |
|
133 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
134 |
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
3 |
class P2P_Query {
|
4 |
|
5 |
+
function expand_shortcut_qv( &$q ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
$qv_map = array(
|
7 |
'connected' => 'any',
|
8 |
'connected_to' => 'to',
|
10 |
);
|
11 |
|
12 |
foreach ( $qv_map as $key => $direction ) {
|
13 |
+
if ( !empty( $q[ $key ] ) ) {
|
14 |
+
$q['connected_items'] = _p2p_pluck( $q, $key );
|
15 |
+
$q['connected_direction'] = $direction;
|
|
|
|
|
|
|
|
|
|
|
16 |
}
|
17 |
}
|
18 |
}
|
19 |
|
20 |
+
function get_qv( $q ) {
|
21 |
+
$qv_list = array(
|
22 |
+
'items', 'direction', 'meta',
|
23 |
+
'orderby', 'order_num', 'order'
|
24 |
+
);
|
25 |
|
26 |
+
foreach ( $qv_list as $key ) {
|
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 |
+
|
42 |
+
$ctypes = (array) _p2p_pluck( $q, 'connected_type' );
|
43 |
+
|
44 |
+
if ( isset( $q['connected_direction'] ) )
|
45 |
+
$directions = (array) _p2p_pluck( $q, 'connected_direction' );
|
46 |
+
else
|
47 |
+
$directions = array();
|
48 |
|
49 |
+
$p2p_types = array();
|
50 |
|
51 |
+
foreach ( $ctypes as $i => $p2p_type ) {
|
52 |
+
$ctype = p2p_type( $p2p_type );
|
53 |
+
|
54 |
+
if ( !$ctype )
|
55 |
+
continue;
|
56 |
+
|
57 |
+
if ( isset( $directions[$i] ) ) {
|
58 |
+
$directed = $ctype->set_direction( $directions[$i] );
|
59 |
+
} else {
|
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
|
74 |
+
$q['p2p_type'] = $p2p_types;
|
75 |
+
|
76 |
+
return true;
|
77 |
+
}
|
78 |
+
|
79 |
+
function alter_clauses( $clauses, $q, $main_id_column ) {
|
80 |
+
global $wpdb;
|
81 |
|
82 |
$clauses['fields'] .= ", $wpdb->p2p.*";
|
83 |
|
84 |
$clauses['join'] .= " INNER JOIN $wpdb->p2p";
|
85 |
|
86 |
+
// Handle main query
|
87 |
+
if ( 'any' == $q['items'] ) {
|
88 |
$search = false;
|
89 |
} else {
|
90 |
+
$search = implode( ',', array_map( 'absint', (array) $q['items'] ) );
|
91 |
}
|
92 |
|
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 );
|
100 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
$fields = array( 'p2p_from', 'p2p_to' );
|
|
|
|
|
102 |
|
103 |
+
switch ( $direction ) {
|
104 |
|
105 |
+
case 'from':
|
106 |
+
$fields = array_reverse( $fields );
|
107 |
+
// fallthrough
|
108 |
+
case 'to':
|
109 |
+
list( $from, $to ) = $fields;
|
110 |
+
|
111 |
+
$part .= " AND $main_id_column = $wpdb->p2p.$from";
|
112 |
+
|
113 |
+
if ( $search ) {
|
114 |
+
$part .= " AND $wpdb->p2p.$to IN ($search)";
|
115 |
+
}
|
116 |
+
|
117 |
+
break;
|
118 |
+
default:
|
119 |
+
if ( $search ) {
|
120 |
+
$part .= " AND (
|
121 |
+
($main_id_column = $wpdb->p2p.p2p_to AND $wpdb->p2p.p2p_from IN ($search)) OR
|
122 |
+
($main_id_column = $wpdb->p2p.p2p_from AND $wpdb->p2p.p2p_to IN ($search))
|
123 |
+
)";
|
124 |
+
} else {
|
125 |
+
$part .= " AND ($main_id_column = $wpdb->p2p.p2p_to OR $main_id_column = $wpdb->p2p.p2p_from)";
|
126 |
+
}
|
127 |
}
|
128 |
+
|
129 |
+
$where_parts[] = '(' . $part . ')';
|
130 |
}
|
131 |
|
132 |
+
if ( 1 == count( $where_parts ) )
|
133 |
+
$clauses['where'] .= " AND " . $where_parts[0];
|
134 |
+
else
|
135 |
+
$clauses['where'] .= " AND (" . implode( ' OR ', $where_parts ) . ")";
|
136 |
+
|
137 |
+
// Handle custom fields
|
138 |
+
if ( !empty( $q['meta'] ) ) {
|
139 |
+
$meta_clauses = _p2p_meta_sql_helper( $q['meta'] );
|
140 |
foreach ( $meta_clauses as $key => $value ) {
|
141 |
$clauses[ $key ] .= $value;
|
142 |
}
|
143 |
}
|
144 |
|
145 |
// Handle ordering
|
146 |
+
if ( $q['orderby'] ) {
|
|
|
147 |
$clauses['join'] .= $wpdb->prepare( "
|
148 |
LEFT JOIN $wpdb->p2pmeta AS p2pm_order ON (
|
149 |
$wpdb->p2p.p2p_id = p2pm_order.p2p_id AND p2pm_order.meta_key = %s
|
150 |
)
|
151 |
+
", $q['orderby'] );
|
152 |
|
153 |
+
$order = ( 'DESC' == strtoupper( $q['order'] ) ) ? 'DESC' : 'ASC';
|
154 |
|
155 |
$field = 'meta_value';
|
156 |
|
157 |
+
if ( $q['order_num'] )
|
158 |
$field .= '+0';
|
159 |
|
160 |
+
$clauses['orderby'] = "p2pm_order.$field $order";
|
161 |
}
|
162 |
|
163 |
return $clauses;
|
164 |
}
|
165 |
|
166 |
+
private function find_direction( $ctype, $arg, $object_type ) {
|
167 |
+
$opposite_side = self::choose_side( $object_type,
|
168 |
+
$ctype->object['from'],
|
169 |
+
$ctype->object['to']
|
170 |
+
);
|
|
|
171 |
|
172 |
+
if ( in_array( $opposite_side, array( 'from', 'to' ) ) )
|
173 |
+
return $ctype->set_direction( $opposite_side );
|
|
|
174 |
|
175 |
+
return $ctype->find_direction( $arg );
|
176 |
}
|
|
|
177 |
|
178 |
+
private static function choose_side( $current, $from, $to ) {
|
179 |
+
if ( $from == $to && $current == $from )
|
180 |
+
return 'any';
|
181 |
+
|
182 |
+
if ( $current == $from )
|
183 |
+
return 'to';
|
184 |
+
|
185 |
+
if ( $current == $to )
|
186 |
+
return 'from';
|
187 |
+
|
188 |
+
return false;
|
189 |
+
}
|
190 |
+
}
|
191 |
|
core/side.php
ADDED
@@ -0,0 +1,199 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
define( 'ADMIN_BOX_PER_PAGE', 5 );
|
4 |
+
|
5 |
+
abstract class P2P_Side {
|
6 |
+
|
7 |
+
public $query_vars;
|
8 |
+
|
9 |
+
function __construct( $query_vars ) {
|
10 |
+
$this->query_vars = $query_vars;
|
11 |
+
}
|
12 |
+
|
13 |
+
function get_base_qv() {
|
14 |
+
return $this->query_vars;
|
15 |
+
}
|
16 |
+
}
|
17 |
+
|
18 |
+
|
19 |
+
class P2P_Side_Post extends P2P_Side {
|
20 |
+
|
21 |
+
public $post_type = array();
|
22 |
+
|
23 |
+
function __construct( $query_vars ) {
|
24 |
+
parent::__construct( $query_vars );
|
25 |
+
|
26 |
+
$this->post_type = $this->query_vars['post_type'];
|
27 |
+
}
|
28 |
+
|
29 |
+
function get_base_qv() {
|
30 |
+
return array_merge( $this->query_vars, array(
|
31 |
+
'post_type' => $this->post_type,
|
32 |
+
'suppress_filters' => false,
|
33 |
+
'ignore_sticky_posts' => true,
|
34 |
+
) );
|
35 |
+
}
|
36 |
+
|
37 |
+
function get_title() {
|
38 |
+
return $this->get_ptype()->labels->name;
|
39 |
+
}
|
40 |
+
|
41 |
+
function get_labels() {
|
42 |
+
return $this->get_ptype()->labels;
|
43 |
+
}
|
44 |
+
|
45 |
+
function check_capability() {
|
46 |
+
return current_user_can( $this->get_ptype()->cap->edit_posts );
|
47 |
+
}
|
48 |
+
|
49 |
+
function do_query( $args ) {
|
50 |
+
return new WP_Query( $args );
|
51 |
+
}
|
52 |
+
|
53 |
+
function abstract_query( $query ) {
|
54 |
+
return (object) array(
|
55 |
+
'items' => $query->posts,
|
56 |
+
'current_page' => max( 1, $query->get('paged') ),
|
57 |
+
'total_pages' => $query->max_num_pages
|
58 |
+
);
|
59 |
+
}
|
60 |
+
|
61 |
+
private static $admin_box_qv = array(
|
62 |
+
'update_post_term_cache' => false,
|
63 |
+
'update_post_meta_cache' => false,
|
64 |
+
'post_status' => 'any',
|
65 |
+
);
|
66 |
+
|
67 |
+
function get_connections_qv() {
|
68 |
+
return array_merge( self::$admin_box_qv, array(
|
69 |
+
'nopaging' => true
|
70 |
+
) );
|
71 |
+
}
|
72 |
+
|
73 |
+
function get_connectable_qv( $item_id, $page, $search, $to_exclude ) {
|
74 |
+
$qv = array_merge( $this->get_base_qv(), self::$admin_box_qv, array(
|
75 |
+
'posts_per_page' => ADMIN_BOX_PER_PAGE,
|
76 |
+
'paged' => $page,
|
77 |
+
) );
|
78 |
+
|
79 |
+
if ( $search ) {
|
80 |
+
$qv['s'] = $search;
|
81 |
+
}
|
82 |
+
|
83 |
+
$qv['post__not_in'] = $to_exclude;
|
84 |
+
|
85 |
+
return $qv;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* @param mixed A post type, a post id, a post object, an array of post ids or of objects.
|
90 |
+
*/
|
91 |
+
function item_recognize( $arg ) {
|
92 |
+
if ( is_array( $arg ) ) {
|
93 |
+
$arg = reset( $arg );
|
94 |
+
}
|
95 |
+
|
96 |
+
if ( is_object( $arg ) ) {
|
97 |
+
$post_type = $arg->post_type;
|
98 |
+
} elseif ( $post_id = (int) $arg ) {
|
99 |
+
$post = get_post( $post_id );
|
100 |
+
if ( !$post )
|
101 |
+
return false;
|
102 |
+
$post_type = $post->post_type;
|
103 |
+
} else {
|
104 |
+
$post_type = $arg;
|
105 |
+
}
|
106 |
+
|
107 |
+
if ( !post_type_exists( $post_type ) )
|
108 |
+
return false;
|
109 |
+
|
110 |
+
return in_array( $post_type, $this->post_type );
|
111 |
+
}
|
112 |
+
|
113 |
+
protected function get_ptype() {
|
114 |
+
return get_post_type_object( $this->post_type[0] );
|
115 |
+
}
|
116 |
+
|
117 |
+
function item_exists( $item_id ) {
|
118 |
+
return (bool) get_post( $item_id );
|
119 |
+
}
|
120 |
+
|
121 |
+
function item_title( $item ) {
|
122 |
+
return $item->post_title;
|
123 |
+
}
|
124 |
+
}
|
125 |
+
|
126 |
+
|
127 |
+
class P2P_Side_Attachment extends P2P_Side_Post {
|
128 |
+
|
129 |
+
function __construct( $query_vars ) {
|
130 |
+
P2P_Side::__construct( $query_vars );
|
131 |
+
|
132 |
+
$this->post_type = array( 'attachment' );
|
133 |
+
}
|
134 |
+
}
|
135 |
+
|
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 ),
|
146 |
+
'search_items' => __( 'Search Users', P2P_TEXTDOMAIN ),
|
147 |
+
'not_found' => __( 'No users found.', P2P_TEXTDOMAIN ),
|
148 |
+
);
|
149 |
+
}
|
150 |
+
|
151 |
+
function check_capability() {
|
152 |
+
return current_user_can( 'list_users' );
|
153 |
+
}
|
154 |
+
|
155 |
+
function do_query( $args ) {
|
156 |
+
return new WP_User_Query( $args );
|
157 |
+
}
|
158 |
+
|
159 |
+
function abstract_query( $query ) {
|
160 |
+
return (object) array(
|
161 |
+
'items' => $query->get_results(),
|
162 |
+
'current_page' => isset( $query->query_vars['_p2p_page'] ) ? $query->query_vars['_p2p_page'] : 1,
|
163 |
+
'total_pages' => ceil( $query->get_total() / ADMIN_BOX_PER_PAGE )
|
164 |
+
);
|
165 |
+
}
|
166 |
+
|
167 |
+
function get_connections_qv() {
|
168 |
+
return array();
|
169 |
+
}
|
170 |
+
|
171 |
+
function get_connectable_qv( $item_id, $page, $search, $to_exclude ) {
|
172 |
+
$qv = array_merge( $this->get_base_qv(), array(
|
173 |
+
'number' => ADMIN_BOX_PER_PAGE,
|
174 |
+
'offset' => ADMIN_BOX_PER_PAGE * ( $page - 1 ),
|
175 |
+
'_p2p_page' => $page
|
176 |
+
) );
|
177 |
+
|
178 |
+
if ( $search ) {
|
179 |
+
$qv['search'] = '*' . $search . '*';
|
180 |
+
}
|
181 |
+
|
182 |
+
$qv['exclude'] = $to_exclude;
|
183 |
+
|
184 |
+
return $qv;
|
185 |
+
}
|
186 |
+
|
187 |
+
function item_recognize( $arg ) {
|
188 |
+
return false;
|
189 |
+
}
|
190 |
+
|
191 |
+
function item_exists( $item_id ) {
|
192 |
+
return (bool) get_user_by( 'id', $item_id );
|
193 |
+
}
|
194 |
+
|
195 |
+
function item_title( $item ) {
|
196 |
+
return $item->display_name;
|
197 |
+
}
|
198 |
+
}
|
199 |
+
|
core/storage.php
CHANGED
@@ -1,23 +1,61 @@
|
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
3 |
class P2P_Storage {
|
4 |
|
5 |
-
|
6 |
-
private function __construct() {}
|
7 |
-
|
8 |
-
private static $version = 3;
|
9 |
|
10 |
function init() {
|
11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
p2p_id bigint(20) unsigned NOT NULL auto_increment,
|
13 |
p2p_from bigint(20) unsigned NOT NULL,
|
14 |
p2p_to bigint(20) unsigned NOT NULL,
|
|
|
15 |
PRIMARY KEY (p2p_id),
|
16 |
KEY p2p_from (p2p_from),
|
17 |
-
KEY p2p_to (p2p_to)
|
|
|
18 |
" );
|
19 |
|
20 |
-
|
21 |
meta_id bigint(20) unsigned NOT NULL auto_increment,
|
22 |
p2p_id bigint(20) unsigned NOT NULL default '0',
|
23 |
meta_key varchar(255) default NULL,
|
@@ -26,190 +64,57 @@ class P2P_Storage {
|
|
26 |
KEY p2p_id (p2p_id),
|
27 |
KEY meta_key (meta_key)
|
28 |
" );
|
29 |
-
|
30 |
-
if ( is_admin() && self::$version != get_option( 'p2p_storage' ) ) {
|
31 |
-
$table->install();
|
32 |
-
$table2->install();
|
33 |
-
|
34 |
-
update_option( 'p2p_storage', self::$version );
|
35 |
-
}
|
36 |
-
|
37 |
-
add_action( 'deleted_post', array( __CLASS__, 'disconnect' ) );
|
38 |
-
}
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Get a list of connections, given a certain post id
|
42 |
-
*
|
43 |
-
* @param int $from post id
|
44 |
-
* @param int|string $to post id or direction: 'from' or 'to'
|
45 |
-
* @param array $data additional data about the connection to filter against
|
46 |
-
*
|
47 |
-
* @return array( p2p_id => post_id ) if $to is string
|
48 |
-
* @return array( p2p_id ) if $to is int
|
49 |
-
*/
|
50 |
-
function get( $post_id, $direction, $data = array() ) {
|
51 |
-
if ( 'any' == $direction ) {
|
52 |
-
$from = self::_get( $post_id, 'from', $data );
|
53 |
-
$to = self::_get( $post_id, 'to', $data );
|
54 |
-
|
55 |
-
// array_merge() doesn't preserve numeric keys
|
56 |
-
return $from + $to;
|
57 |
-
}
|
58 |
-
|
59 |
-
return self::_get( $post_id, $direction, $data );
|
60 |
}
|
61 |
|
62 |
-
|
63 |
global $wpdb;
|
64 |
|
65 |
-
$
|
66 |
-
$where = '';
|
67 |
-
$join = '';
|
68 |
-
|
69 |
-
$_return_p2p_ids = false;
|
70 |
-
switch ( $to ) {
|
71 |
-
case 'from':
|
72 |
-
$fields .= ', p2p_to AS post_id';
|
73 |
-
$where .= $wpdb->prepare( "p2p_from = %d", $from );
|
74 |
-
break;
|
75 |
-
|
76 |
-
case 'to':
|
77 |
-
$fields .= ', p2p_from AS post_id';
|
78 |
-
$where .= $wpdb->prepare( "p2p_to = %d", $from );
|
79 |
-
break;
|
80 |
-
|
81 |
-
default:
|
82 |
-
$where .= $wpdb->prepare( "p2p_from = %d AND p2p_to = %d", $from, $to );
|
83 |
-
$_return_p2p_ids = true;
|
84 |
-
}
|
85 |
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
$where .= $clauses['where'];
|
90 |
-
}
|
91 |
|
92 |
-
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
-
|
95 |
-
return $wpdb->get_col( $query );
|
96 |
|
97 |
-
|
|
|
|
|
|
|
98 |
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
|
103 |
-
return $
|
104 |
}
|
105 |
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
* @param int $from post id
|
110 |
-
* @param int $to post id
|
111 |
-
* @param array $data additional data about the connection
|
112 |
-
*
|
113 |
-
* @return int|bool connection id or False on failure
|
114 |
-
*/
|
115 |
-
function connect( $from, $to, $data = array() ) {
|
116 |
-
global $wpdb;
|
117 |
-
|
118 |
-
$from = absint( $from );
|
119 |
-
$to = absint( $to );
|
120 |
-
|
121 |
-
if ( !$from || !$to )
|
122 |
-
return false;
|
123 |
-
|
124 |
-
$wpdb->insert( $wpdb->p2p, array( 'p2p_from' => $from, 'p2p_to' => $to ), '%d' );
|
125 |
|
126 |
-
|
127 |
-
|
128 |
-
foreach ( $data as $key => $value )
|
129 |
-
p2p_add_meta( $p2p_id, $key, $value );
|
130 |
-
|
131 |
-
return $p2p_id;
|
132 |
-
}
|
133 |
-
|
134 |
-
/**
|
135 |
-
* Disconnect two posts
|
136 |
-
*
|
137 |
-
* @param int $from post id
|
138 |
-
* @param int|string $to post id or direction: 'from' or 'to'
|
139 |
-
* @param array $data additional data about the connection to filter against
|
140 |
-
*
|
141 |
-
* @return int Number of connections deleted
|
142 |
-
*/
|
143 |
-
function disconnect( $from, $to = 'any', $data = array() ) {
|
144 |
-
$connections = self::get( $from, $to, $data );
|
145 |
-
|
146 |
-
// We're interested in the p2p_ids
|
147 |
-
if ( !(int) $to )
|
148 |
-
$connections = array_keys( $connections );
|
149 |
-
|
150 |
-
return self::delete( $connections );
|
151 |
}
|
152 |
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
if ( empty( $p2p_id ) )
|
164 |
-
return 0;
|
165 |
-
|
166 |
-
$p2p_ids = array_map( 'absint', (array) $p2p_id );
|
167 |
-
|
168 |
-
$where = "WHERE p2p_id IN (" . implode( ',', $p2p_ids ) . ")";
|
169 |
-
|
170 |
-
$wpdb->query( "DELETE FROM $wpdb->p2p $where" );
|
171 |
-
$wpdb->query( "DELETE FROM $wpdb->p2pmeta $where" );
|
172 |
-
|
173 |
-
return count( $p2p_ids );
|
174 |
}
|
175 |
}
|
176 |
|
177 |
P2P_Storage::init();
|
178 |
|
179 |
-
|
180 |
-
function p2p_get_meta($p2p_id, $key, $single = false) {
|
181 |
-
return get_metadata('p2p', $p2p_id, $key, $single);
|
182 |
-
}
|
183 |
-
|
184 |
-
function p2p_update_meta($p2p_id, $meta_key, $meta_value, $prev_value = '') {
|
185 |
-
return update_metadata('p2p', $p2p_id, $meta_key, $meta_value, $prev_value);
|
186 |
-
}
|
187 |
-
|
188 |
-
function p2p_add_meta($p2p_id, $meta_key, $meta_value, $unique = false) {
|
189 |
-
return add_metadata('p2p', $p2p_id, $meta_key, $meta_value, $unique);
|
190 |
-
}
|
191 |
-
|
192 |
-
function p2p_delete_meta($p2p_id, $meta_key, $meta_value = '') {
|
193 |
-
return delete_metadata('p2p', $p2p_id, $meta_key, $meta_value);
|
194 |
-
}
|
195 |
-
|
196 |
-
/**
|
197 |
-
* @internal
|
198 |
-
*/
|
199 |
-
function _p2p_meta_sql_helper( $data ) {
|
200 |
-
global $wpdb;
|
201 |
-
|
202 |
-
if ( isset( $data[0] ) ) {
|
203 |
-
$meta_query = $data;
|
204 |
-
}
|
205 |
-
else {
|
206 |
-
$meta_query = array();
|
207 |
-
|
208 |
-
foreach ( $data as $key => $value ) {
|
209 |
-
$meta_query[] = compact( 'key', 'value' );
|
210 |
-
}
|
211 |
-
}
|
212 |
-
|
213 |
-
return get_meta_sql( $meta_query, 'p2p', $wpdb->p2p, 'p2p_id' );
|
214 |
-
}
|
215 |
-
|
1 |
<?php
|
2 |
|
3 |
+
/**
|
4 |
+
* Handles various db-related tasks
|
5 |
+
*/
|
6 |
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,
|
50 |
p2p_to bigint(20) unsigned NOT NULL,
|
51 |
+
p2p_type varchar(44) NOT NULL default '',
|
52 |
PRIMARY KEY (p2p_id),
|
53 |
KEY p2p_from (p2p_from),
|
54 |
+
KEY p2p_to (p2p_to),
|
55 |
+
KEY p2p_type (p2p_type)
|
56 |
" );
|
57 |
|
58 |
+
scb_install_table( 'p2pmeta', "
|
59 |
meta_id bigint(20) unsigned NOT NULL auto_increment,
|
60 |
p2p_id bigint(20) unsigned NOT NULL default '0',
|
61 |
meta_key varchar(255) default NULL,
|
64 |
KEY p2p_id (p2p_id),
|
65 |
KEY meta_key (meta_key)
|
66 |
" );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
}
|
68 |
|
69 |
+
function upgrade() {
|
70 |
global $wpdb;
|
71 |
|
72 |
+
$n = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
|
74 |
+
foreach ( P2P_Connection_Type_Factory::get_all_instances() as $p2p_type => $ctype ) {
|
75 |
+
if ( ! $ctype instanceof P2P_Connection_Type )
|
76 |
+
continue;
|
|
|
|
|
77 |
|
78 |
+
$args = $ctype->set_direction( 'any' )->get_connected_args( array(
|
79 |
+
'connected_items' => 'any',
|
80 |
+
'cache_results' => false,
|
81 |
+
'post_status' => 'any',
|
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
|
89 |
+
if ( $post->p2p_type )
|
90 |
+
continue;
|
91 |
|
92 |
+
$n += $wpdb->update( $wpdb->p2p, compact( 'p2p_type' ), array( 'p2p_id' => $post->p2p_id ) );
|
93 |
+
}
|
94 |
+
}
|
95 |
|
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 |
+
}
|
115 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
}
|
117 |
}
|
118 |
|
119 |
P2P_Storage::init();
|
120 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core/type-factory.php
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class P2P_Connection_Type_Factory {
|
4 |
+
private static $instances = array();
|
5 |
+
|
6 |
+
public static function register( $args ) {
|
7 |
+
if ( isset( $args['name'] ) ) {
|
8 |
+
if ( strlen( $args['name'] ) > 44 ) {
|
9 |
+
trigger_error( sprintf( "Connection name '%s' is longer than 44 characters.", $args['name'] ), E_USER_WARNING );
|
10 |
+
return false;
|
11 |
+
}
|
12 |
+
} else {
|
13 |
+
trigger_error( "Connection types without a 'name' parameter are deprecated.", E_USER_WARNING );
|
14 |
+
}
|
15 |
+
|
16 |
+
$args = wp_parse_args( $args, array(
|
17 |
+
'name' => false,
|
18 |
+
'from_object' => 'post',
|
19 |
+
'to_object' => 'post',
|
20 |
+
'from' => 'post',
|
21 |
+
'to' => 'post',
|
22 |
+
'from_query_vars' => array(),
|
23 |
+
'to_query_vars' => array(),
|
24 |
+
'data' => array(),
|
25 |
+
'cardinality' => 'many-to-many',
|
26 |
+
'prevent_duplicates' => true,
|
27 |
+
'self_connections' => false,
|
28 |
+
'sortable' => false,
|
29 |
+
'title' => array(),
|
30 |
+
'from_labels' => '',
|
31 |
+
'to_labels' => '',
|
32 |
+
'reciprocal' => false,
|
33 |
+
) );
|
34 |
+
|
35 |
+
$sides = array();
|
36 |
+
|
37 |
+
foreach ( array( 'from', 'to' ) as $direction ) {
|
38 |
+
$object = _p2p_pluck( $args, $direction );
|
39 |
+
|
40 |
+
if ( 'user' == $object )
|
41 |
+
$args[ $direction . '_object' ] = 'user';
|
42 |
+
elseif ( 'attachment' == $object )
|
43 |
+
$args[ $direction . '_object' ] = 'attachment';
|
44 |
+
|
45 |
+
if ( 'post' == $args[ $direction . '_object' ] ) {
|
46 |
+
$validated = array();
|
47 |
+
|
48 |
+
foreach ( (array) $object as $ptype ) {
|
49 |
+
if ( !post_type_exists( $ptype ) ) {
|
50 |
+
trigger_error( "Post type '$ptype' is not defined." );
|
51 |
+
} else {
|
52 |
+
$validated[] = $ptype;
|
53 |
+
}
|
54 |
+
}
|
55 |
+
|
56 |
+
if ( empty( $validated ) )
|
57 |
+
$validated = array( 'post' );
|
58 |
+
|
59 |
+
$args[ $direction . '_query_vars' ]['post_type'] = $validated;
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
+
if ( !$args['name'] ) {
|
64 |
+
$args['name'] = md5( serialize( array_values( wp_array_slice_assoc( $args, array(
|
65 |
+
'from_object', 'to_object',
|
66 |
+
'from_query_vars', 'to_query_vars',
|
67 |
+
'data'
|
68 |
+
) ) ) ) );
|
69 |
+
}
|
70 |
+
|
71 |
+
if ( $args['from_object'] == $args['to_object'] && 'post' == $args['from_object'] )
|
72 |
+
$class = 'P2P_Connection_Type';
|
73 |
+
else
|
74 |
+
$class = 'Generic_Connection_Type';
|
75 |
+
|
76 |
+
$args = apply_filters( 'p2p_connection_type_args', $args );
|
77 |
+
|
78 |
+
$ctype = new $class( $args );
|
79 |
+
|
80 |
+
if ( isset( self::$instances[ $ctype->name ] ) ) {
|
81 |
+
trigger_error( "Connection type '$ctype->name' is already defined.", E_USER_NOTICE );
|
82 |
+
}
|
83 |
+
|
84 |
+
self::$instances[ $ctype->name ] = $ctype;
|
85 |
+
|
86 |
+
return $ctype;
|
87 |
+
}
|
88 |
+
|
89 |
+
public static function get_all_instances() {
|
90 |
+
return self::$instances;
|
91 |
+
}
|
92 |
+
|
93 |
+
public static function get_instance( $hash ) {
|
94 |
+
if ( isset( self::$instances[ $hash ] ) )
|
95 |
+
return self::$instances[ $hash ];
|
96 |
+
|
97 |
+
return false;
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
core/type.php
CHANGED
@@ -1,91 +1,93 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
class
|
4 |
-
|
5 |
-
private static $instances = array();
|
6 |
-
|
7 |
-
public function register( $args ) {
|
8 |
-
$args = wp_parse_args( $args, array(
|
9 |
-
'id' => false,
|
10 |
-
'from' => '',
|
11 |
-
'to' => '',
|
12 |
-
'from_query_vars' => array(),
|
13 |
-
'to_query_vars' => array(),
|
14 |
-
'data' => array(),
|
15 |
-
'reciprocal' => false,
|
16 |
-
'cardinality' => 'many-to-many',
|
17 |
-
'prevent_duplicates' => true,
|
18 |
-
'sortable' => false,
|
19 |
-
'title' => '',
|
20 |
-
) );
|
21 |
|
22 |
-
|
23 |
-
if ( isset( $args[ $key ] ) ) {
|
24 |
-
$args["{$key}_query_vars"]['post_type'] = (array) $args[ $key ];
|
25 |
-
unset( $args[ $key ] );
|
26 |
-
}
|
27 |
|
28 |
-
|
29 |
-
$args["{$key}_query_vars"]['post_type'] = array( 'post' );
|
30 |
-
}
|
31 |
|
32 |
-
|
33 |
|
34 |
-
|
35 |
-
|
36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
|
38 |
-
|
39 |
-
|
|
|
40 |
}
|
41 |
|
42 |
-
|
43 |
-
}
|
44 |
|
45 |
-
|
46 |
-
return self::$instances;
|
47 |
-
}
|
48 |
|
49 |
-
|
50 |
-
if ( isset( self::$instances[ $hash ] ) )
|
51 |
-
return self::$instances[ $hash ];
|
52 |
|
53 |
-
|
|
|
|
|
54 |
}
|
55 |
|
|
|
|
|
56 |
|
57 |
-
|
58 |
-
|
59 |
|
60 |
-
|
61 |
-
|
|
|
|
|
|
|
62 |
|
63 |
-
|
|
|
|
|
64 |
|
65 |
-
|
66 |
-
|
|
|
|
|
67 |
|
68 |
-
|
|
|
69 |
}
|
70 |
|
71 |
-
|
72 |
-
if (
|
73 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
|
75 |
-
|
76 |
-
return $this->indeterminate;
|
77 |
|
78 |
-
|
79 |
-
|
|
|
|
|
|
|
80 |
|
81 |
-
|
82 |
-
return isset( $this->args[$key] );
|
83 |
}
|
84 |
|
85 |
public function __call( $method, $args ) {
|
86 |
$directed = $this->find_direction( $args[0] );
|
87 |
-
if ( !$directed )
|
|
|
88 |
return false;
|
|
|
89 |
|
90 |
return call_user_func_array( array( $directed, $method ), $args );
|
91 |
}
|
@@ -97,14 +99,14 @@ class P2P_Connection_Type {
|
|
97 |
*
|
98 |
* @return object P2P_Directed_Connection_Type instance
|
99 |
*/
|
100 |
-
public function set_direction( $direction ) {
|
101 |
if ( !in_array( $direction, array( 'from', 'to', 'any' ) ) )
|
102 |
return false;
|
103 |
|
104 |
-
if ( $
|
105 |
-
return new
|
106 |
|
107 |
-
return
|
108 |
}
|
109 |
|
110 |
/**
|
@@ -116,21 +118,17 @@ class P2P_Connection_Type {
|
|
116 |
* @return bool|object|string False on failure, P2P_Directed_Connection_Type instance or direction on success.
|
117 |
*/
|
118 |
public function find_direction( $arg, $instantiate = true ) {
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
$direction = P2P_Util::get_direction( $post_type, $this->from, $this->to );
|
124 |
-
if ( !$direction )
|
125 |
-
return false;
|
126 |
|
127 |
-
|
128 |
-
|
129 |
|
130 |
-
|
131 |
-
|
132 |
|
133 |
-
return
|
134 |
}
|
135 |
|
136 |
/**
|
@@ -140,8 +138,9 @@ class P2P_Connection_Type {
|
|
140 |
*
|
141 |
* @param object $query WP_Query instance.
|
142 |
* @param string|array $extra_qv Additional query vars for the inner query.
|
|
|
143 |
*/
|
144 |
-
public function each_connected( $query, $extra_qv = array() ) {
|
145 |
if ( empty( $query->posts ) || !is_object( $query->posts[0] ) )
|
146 |
return;
|
147 |
|
@@ -153,8 +152,6 @@ class P2P_Connection_Type {
|
|
153 |
if ( !$directed )
|
154 |
return false;
|
155 |
|
156 |
-
$prop_name = 'connected';
|
157 |
-
|
158 |
$posts = array();
|
159 |
|
160 |
foreach ( $query->posts as $post ) {
|
@@ -170,26 +167,39 @@ class P2P_Connection_Type {
|
|
170 |
}
|
171 |
$extra_qv['nopaging'] = true;
|
172 |
|
173 |
-
$q = $directed->get_connected( array_keys( $posts ), $extra_qv );
|
174 |
-
|
175 |
-
foreach ( $q->posts as $inner_post ) {
|
176 |
-
if ( $inner_post->ID == $inner_post->p2p_from )
|
177 |
-
$outer_post_id = $inner_post->p2p_to;
|
178 |
-
elseif ( $inner_post->ID == $inner_post->p2p_to )
|
179 |
-
$outer_post_id = $inner_post->p2p_from;
|
180 |
-
else {
|
181 |
-
trigger_error( "Corrupted data for post $inner_post->ID", E_USER_WARNING );
|
182 |
-
continue;
|
183 |
-
}
|
184 |
|
185 |
-
|
186 |
-
|
|
|
|
|
|
|
|
|
|
|
187 |
continue;
|
188 |
}
|
189 |
|
190 |
-
array_push( $posts[ $
|
191 |
}
|
192 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
|
194 |
/**
|
195 |
* Get a list of posts connected to other posts connected to a post.
|
@@ -277,14 +287,5 @@ class P2P_Connection_Type {
|
|
277 |
|
278 |
return $adjacent[0];
|
279 |
}
|
280 |
-
|
281 |
-
/**
|
282 |
-
* Delete a connection.
|
283 |
-
*
|
284 |
-
* @param int p2p_id
|
285 |
-
*/
|
286 |
-
public function delete_connection( $p2p_id ) {
|
287 |
-
return P2P_Storage::delete( $p2p_id );
|
288 |
-
}
|
289 |
}
|
290 |
|
1 |
<?php
|
2 |
|
3 |
+
class Generic_Connection_Type {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
+
public $indeterminate = false;
|
|
|
|
|
|
|
|
|
6 |
|
7 |
+
public $object;
|
|
|
|
|
8 |
|
9 |
+
public $side;
|
10 |
|
11 |
+
public $cardinality;
|
12 |
+
|
13 |
+
public $title;
|
14 |
+
|
15 |
+
public $labels;
|
16 |
+
|
17 |
+
public function __construct( $args ) {
|
18 |
+
foreach ( array( 'from', 'to' ) as $direction ) {
|
19 |
+
$this->object[ $direction ] = _p2p_pluck( $args, $direction . '_object' );
|
20 |
|
21 |
+
$class = 'P2P_Side_' . ucfirst( $this->object[ $direction ] );
|
22 |
+
|
23 |
+
$this->side[ $direction ] = new $class( _p2p_pluck( $args, $direction . '_query_vars' ) );
|
24 |
}
|
25 |
|
26 |
+
$this->set_cardinality( _p2p_pluck( $args, 'cardinality' ) );
|
|
|
27 |
|
28 |
+
$this->set_labels( $args );
|
|
|
|
|
29 |
|
30 |
+
$this->title = $this->expand_title( _p2p_pluck( $args, 'title' ) );
|
|
|
|
|
31 |
|
32 |
+
foreach ( $args as $key => $value ) {
|
33 |
+
$this->$key = $value;
|
34 |
+
}
|
35 |
}
|
36 |
|
37 |
+
private function set_cardinality( $cardinality ) {
|
38 |
+
$parts = explode( '-', $cardinality );
|
39 |
|
40 |
+
$this->cardinality['from'] = $parts[0];
|
41 |
+
$this->cardinality['to'] = $parts[2];
|
42 |
|
43 |
+
foreach ( $this->cardinality as $key => &$value ) {
|
44 |
+
if ( 'one' != $value )
|
45 |
+
$value = 'many';
|
46 |
+
}
|
47 |
+
}
|
48 |
|
49 |
+
private function set_labels( &$args ) {
|
50 |
+
foreach ( array( 'from', 'to' ) as $key ) {
|
51 |
+
$labels = _p2p_pluck( $args, $key . '_labels' );
|
52 |
|
53 |
+
if ( empty( $labels ) )
|
54 |
+
$labels = $this->side[ $key ]->get_labels();
|
55 |
+
else
|
56 |
+
$labels = (object) $labels;
|
57 |
|
58 |
+
$this->labels[ $key ] = $labels;
|
59 |
+
}
|
60 |
}
|
61 |
|
62 |
+
private function expand_title( $title ) {
|
63 |
+
if ( $title && !is_array( $title ) ) {
|
64 |
+
return array(
|
65 |
+
'from' => $title,
|
66 |
+
'to' => $title,
|
67 |
+
);
|
68 |
+
}
|
69 |
+
|
70 |
+
foreach ( array( 'from', 'to' ) as $key ) {
|
71 |
+
if ( isset( $title[$key] ) )
|
72 |
+
continue;
|
73 |
|
74 |
+
$other_key = ( 'from' == $key ) ? 'to' : 'from';
|
|
|
75 |
|
76 |
+
$title[$key] = sprintf(
|
77 |
+
__( 'Connected %s', P2P_TEXTDOMAIN ),
|
78 |
+
$this->side[ $other_key ]->get_title()
|
79 |
+
);
|
80 |
+
}
|
81 |
|
82 |
+
return $title;
|
|
|
83 |
}
|
84 |
|
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 |
|
92 |
return call_user_func_array( array( $directed, $method ), $args );
|
93 |
}
|
99 |
*
|
100 |
* @return object P2P_Directed_Connection_Type instance
|
101 |
*/
|
102 |
+
public function set_direction( $direction, $instantiate = true ) {
|
103 |
if ( !in_array( $direction, array( 'from', 'to', 'any' ) ) )
|
104 |
return false;
|
105 |
|
106 |
+
if ( $instantiate )
|
107 |
+
return new P2P_Directed_Connection_Type( $this, $direction );
|
108 |
|
109 |
+
return $direction;
|
110 |
}
|
111 |
|
112 |
/**
|
118 |
* @return bool|object|string False on failure, P2P_Directed_Connection_Type instance or direction on success.
|
119 |
*/
|
120 |
public function find_direction( $arg, $instantiate = true ) {
|
121 |
+
foreach ( array( 'from', 'to' ) as $direction ) {
|
122 |
+
if ( !$this->side[ $direction ]->item_recognize( $arg ) )
|
123 |
+
continue;
|
|
|
|
|
|
|
|
|
124 |
|
125 |
+
if ( $this->indeterminate )
|
126 |
+
$direction = $this->reciprocal ? 'any' : 'from';
|
127 |
|
128 |
+
return $this->set_direction( $direction, $instantiate );
|
129 |
+
}
|
130 |
|
131 |
+
return false;
|
132 |
}
|
133 |
|
134 |
/**
|
138 |
*
|
139 |
* @param object $query WP_Query instance.
|
140 |
* @param string|array $extra_qv Additional query vars for the inner query.
|
141 |
+
* @param string $prop_name The name of the property used to store the list of connected items on each post object.
|
142 |
*/
|
143 |
+
public function each_connected( $query, $extra_qv = array(), $prop_name = 'connected' ) {
|
144 |
if ( empty( $query->posts ) || !is_object( $query->posts[0] ) )
|
145 |
return;
|
146 |
|
152 |
if ( !$directed )
|
153 |
return false;
|
154 |
|
|
|
|
|
155 |
$posts = array();
|
156 |
|
157 |
foreach ( $query->posts as $post ) {
|
167 |
}
|
168 |
$extra_qv['nopaging'] = true;
|
169 |
|
170 |
+
$q = $directed->get_connected( array_keys( $posts ), $extra_qv, 'abstract' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
|
172 |
+
foreach ( $q->items as $inner_item ) {
|
173 |
+
if ( $inner_item->ID == $inner_item->p2p_from ) {
|
174 |
+
$outer_item_id = $inner_item->p2p_to;
|
175 |
+
} elseif ( $inner_item->ID == $inner_item->p2p_to ) {
|
176 |
+
$outer_item_id = $inner_item->p2p_from;
|
177 |
+
} else {
|
178 |
+
trigger_error( "Corrupted data for item $inner_item->ID", E_USER_WARNING );
|
179 |
continue;
|
180 |
}
|
181 |
|
182 |
+
array_push( $posts[ $outer_item_id ]->$prop_name, $inner_item );
|
183 |
}
|
184 |
}
|
185 |
+
}
|
186 |
+
|
187 |
+
|
188 |
+
class P2P_Connection_Type extends Generic_Connection_Type {
|
189 |
+
|
190 |
+
public function __construct( $args ) {
|
191 |
+
parent::__construct( $args );
|
192 |
+
|
193 |
+
$common = array_intersect( $this->from, $this->to );
|
194 |
+
|
195 |
+
if ( !empty( $common ) )
|
196 |
+
$this->indeterminate = true;
|
197 |
+
}
|
198 |
+
|
199 |
+
public function __get( $key ) {
|
200 |
+
if ( 'from' == $key || 'to' == $key )
|
201 |
+
return $this->side[ $key ]->post_type;
|
202 |
+
}
|
203 |
|
204 |
/**
|
205 |
* Get a list of posts connected to other posts connected to a post.
|
287 |
|
288 |
return $adjacent[0];
|
289 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
290 |
}
|
291 |
|
core/url-query.php
CHANGED
@@ -4,31 +4,14 @@ class P2P_URL_Query {
|
|
4 |
|
5 |
function init() {
|
6 |
add_filter( 'query_vars', array( __CLASS__, 'query_vars' ) );
|
7 |
-
add_filter( 'request', array( __CLASS__, 'request' ) );
|
8 |
}
|
9 |
|
10 |
function query_vars( $public_qv ) {
|
11 |
-
$public_qv
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
function request( $request ) {
|
18 |
-
if ( !isset( $request['connected_type'] ) || !isset( $request['connected'] ) )
|
19 |
-
return $request;
|
20 |
-
|
21 |
-
$connected_arg = _p2p_pluck( $request, 'connected' );
|
22 |
-
|
23 |
-
$ctype = p2p_type( _p2p_pluck( $request, 'connected_type' ) );
|
24 |
-
if ( !$ctype )
|
25 |
-
return array( 'year' => 2525 );
|
26 |
-
|
27 |
-
$directed = $ctype->find_direction( $connected_arg );
|
28 |
-
if ( !$directed )
|
29 |
-
return array( 'year' => 2525 );
|
30 |
-
|
31 |
-
return $directed->get_connected_args( $connected_arg, $request );
|
32 |
}
|
33 |
}
|
34 |
|
4 |
|
5 |
function init() {
|
6 |
add_filter( 'query_vars', array( __CLASS__, 'query_vars' ) );
|
|
|
7 |
}
|
8 |
|
9 |
function query_vars( $public_qv ) {
|
10 |
+
return array_merge( $public_qv, array(
|
11 |
+
'connected_type',
|
12 |
+
'connected_items',
|
13 |
+
'connected_direction',
|
14 |
+
) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
}
|
16 |
}
|
17 |
|
core/util.php
CHANGED
@@ -1,123 +1,59 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
/**
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Attempt to find a post type.
|
12 |
-
*
|
13 |
-
* @param mixed A post type, a post id, a post object, an array of post ids or of objects.
|
14 |
-
*
|
15 |
-
* @return bool|string False on failure, post type on success.
|
16 |
-
*/
|
17 |
-
static function find_post_type( $arg ) {
|
18 |
-
if ( is_array( $arg ) ) {
|
19 |
-
$arg = reset( $arg );
|
20 |
-
}
|
21 |
-
|
22 |
-
if ( is_object( $arg ) ) {
|
23 |
-
$post_type = $arg->post_type;
|
24 |
-
} elseif ( $post_id = (int) $arg ) {
|
25 |
-
$post = get_post( $post_id );
|
26 |
-
if ( !$post )
|
27 |
-
return false;
|
28 |
-
$post_type = $post->post_type;
|
29 |
-
} else {
|
30 |
-
$post_type = $arg;
|
31 |
-
}
|
32 |
-
|
33 |
-
if ( !post_type_exists( $post_type ) )
|
34 |
-
return false;
|
35 |
-
|
36 |
-
return $post_type;
|
37 |
-
}
|
38 |
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
} while ( !$ptype && !empty( $post_types ) );
|
43 |
|
44 |
-
|
|
|
45 |
}
|
|
|
|
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
*
|
50 |
-
* @param string A post type to check against.
|
51 |
-
* @param array List of post types (from).
|
52 |
-
* @param array List of post types (to).
|
53 |
-
*
|
54 |
-
* @return bool|string False on failure, direction on success.
|
55 |
-
*/
|
56 |
-
static function get_direction( $post_type, $from, $to ) {
|
57 |
-
if ( in_array( $post_type, $from ) ) {
|
58 |
-
$direction = 'from';
|
59 |
-
} elseif ( in_array( $post_type, $to ) ) {
|
60 |
-
$direction = 'to';
|
61 |
-
} else {
|
62 |
-
$direction = false;
|
63 |
}
|
64 |
-
|
65 |
-
return $direction;
|
66 |
-
}
|
67 |
-
|
68 |
-
/**
|
69 |
-
* @param string The direction in which ordering is allowed
|
70 |
-
* @param string The current direction
|
71 |
-
*
|
72 |
-
* @return bool|string False on failure, the connection field key otherwise
|
73 |
-
*/
|
74 |
-
static function get_orderby_key( $ordering_direction, $connection_direction ) {
|
75 |
-
if ( !$ordering_direction || 'any' == $connection_direction )
|
76 |
-
return false;
|
77 |
-
|
78 |
-
if ( 'any' == $ordering_direction || $connection_direction == $ordering_direction )
|
79 |
-
return '_order_' . $connection_direction;
|
80 |
-
|
81 |
-
if ( 'from' == $connection_direction )
|
82 |
-
return $ordering_direction;
|
83 |
-
|
84 |
-
return false;
|
85 |
-
}
|
86 |
-
|
87 |
-
static function get_ptype_label( $ptypes ) {
|
88 |
-
return get_post_type_object( $ptypes[0] )->labels->name;
|
89 |
}
|
90 |
|
91 |
-
|
92 |
-
|
93 |
-
$title = array();
|
94 |
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
|
102 |
-
|
103 |
-
|
104 |
-
|
|
|
105 |
|
106 |
-
|
|
|
|
|
|
|
107 |
|
108 |
-
|
109 |
-
|
110 |
-
P2P_Util::get_ptype_label( $$other_key )
|
111 |
-
);
|
112 |
-
}
|
113 |
|
114 |
-
|
115 |
-
}
|
116 |
}
|
117 |
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
|
|
|
|
122 |
}
|
123 |
|
1 |
<?php
|
2 |
|
3 |
+
/** @internal */
|
4 |
+
function _p2p_expand_direction( $direction ) {
|
5 |
+
if ( 'any' == $direction )
|
6 |
+
return array( 'from', 'to' );
|
7 |
+
else
|
8 |
+
return array( $direction );
|
9 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
+
/** @internal */
|
12 |
+
function _p2p_meta_sql_helper( $data ) {
|
13 |
+
global $wpdb;
|
|
|
14 |
|
15 |
+
if ( isset( $data[0] ) ) {
|
16 |
+
$meta_query = $data;
|
17 |
}
|
18 |
+
else {
|
19 |
+
$meta_query = array();
|
20 |
|
21 |
+
foreach ( $data as $key => $value ) {
|
22 |
+
$meta_query[] = compact( 'key', 'value' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
}
|
25 |
|
26 |
+
return get_meta_sql( $meta_query, 'p2p', $wpdb->p2p, 'p2p_id' );
|
27 |
+
}
|
|
|
28 |
|
29 |
+
/** @internal */
|
30 |
+
function _p2p_pluck( &$arr, $key ) {
|
31 |
+
$value = $arr[ $key ];
|
32 |
+
unset( $arr[ $key ] );
|
33 |
+
return $value;
|
34 |
+
}
|
35 |
|
36 |
+
/** @internal */
|
37 |
+
function _p2p_append( &$arr, $values ) {
|
38 |
+
$arr = array_merge( $arr, $values );
|
39 |
+
}
|
40 |
|
41 |
+
/** @internal */
|
42 |
+
function _p2p_get_field_type( $args ) {
|
43 |
+
if ( isset( $args['type'] ) )
|
44 |
+
return $args['type'];
|
45 |
|
46 |
+
if ( isset( $args['values'] ) && is_array( $args['values'] ) )
|
47 |
+
return 'select';
|
|
|
|
|
|
|
48 |
|
49 |
+
return 'text';
|
|
|
50 |
}
|
51 |
|
52 |
+
/** @internal */
|
53 |
+
function _p2p_first( $args ) {
|
54 |
+
if ( empty( $args ) )
|
55 |
+
return false;
|
56 |
+
|
57 |
+
return reset( $args );
|
58 |
}
|
59 |
|
core/widget.php
CHANGED
@@ -7,8 +7,8 @@ class P2P_Widget extends scbWidget {
|
|
7 |
'listing' => 'connected'
|
8 |
);
|
9 |
|
10 |
-
static function init(
|
11 |
-
parent::init( __CLASS__,
|
12 |
}
|
13 |
|
14 |
function __construct() {
|
@@ -21,7 +21,14 @@ class P2P_Widget extends scbWidget {
|
|
21 |
if ( empty( $instance ) )
|
22 |
$instance = $this->defaults;
|
23 |
|
24 |
-
$ctypes =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
|
26 |
echo html( 'p', $this->input( array(
|
27 |
'type' => 'select',
|
@@ -64,11 +71,11 @@ class P2P_Widget extends scbWidget {
|
|
64 |
$connected = $ctype->get_related( $post_id );
|
65 |
$title = sprintf(
|
66 |
__( 'Related %s', P2P_TEXTDOMAIN ),
|
67 |
-
|
68 |
);
|
69 |
} else {
|
70 |
$connected = $directed->get_connected( $post_id );
|
71 |
-
$title = $directed->
|
72 |
}
|
73 |
|
74 |
if ( !$connected->have_posts() )
|
@@ -100,7 +107,7 @@ class P2P_Widget extends scbWidget {
|
|
100 |
|
101 |
$label = "$from $arrow $to";
|
102 |
|
103 |
-
$title = $ctype->
|
104 |
|
105 |
if ( $title )
|
106 |
$label .= " ($title)";
|
7 |
'listing' => 'connected'
|
8 |
);
|
9 |
|
10 |
+
static function init() {
|
11 |
+
parent::init( __CLASS__, false, 'p2p' );
|
12 |
}
|
13 |
|
14 |
function __construct() {
|
21 |
if ( empty( $instance ) )
|
22 |
$instance = $this->defaults;
|
23 |
|
24 |
+
$ctypes = array();
|
25 |
+
|
26 |
+
foreach ( P2P_Connection_Type_Factory::get_all_instances() as $p2p_type => $ctype ) {
|
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(
|
34 |
'type' => 'select',
|
71 |
$connected = $ctype->get_related( $post_id );
|
72 |
$title = sprintf(
|
73 |
__( 'Related %s', P2P_TEXTDOMAIN ),
|
74 |
+
$directed->get_current( 'side' )->get_title()
|
75 |
);
|
76 |
} else {
|
77 |
$connected = $directed->get_connected( $post_id );
|
78 |
+
$title = $directed->get_current( 'title' );
|
79 |
}
|
80 |
|
81 |
if ( !$connected->have_posts() )
|
107 |
|
108 |
$label = "$from $arrow $to";
|
109 |
|
110 |
+
$title = $ctype->title[ 'from' ];
|
111 |
|
112 |
if ( $title )
|
113 |
$label .= " ($title)";
|
lang/posts-to-posts-de_DE.mo
ADDED
Binary file
|
lang/posts-to-posts-de_DE.po
ADDED
@@ -0,0 +1,133 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (C) 2011
|
2 |
+
# This file is distributed under the same license as the package.
|
3 |
+
msgid ""
|
4 |
+
msgstr ""
|
5 |
+
"Project-Id-Version: Posts 2 Posts 1.1.4\n"
|
6 |
+
"Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
|
7 |
+
"POT-Creation-Date: 2011-12-01 16:28:04+00:00\n"
|
8 |
+
"MIME-Version: 1.0\n"
|
9 |
+
"Content-Type: text/plain; charset=UTF-8\n"
|
10 |
+
"Content-Transfer-Encoding: 8bit\n"
|
11 |
+
"PO-Revision-Date: 2012-01-24 13:03+0100\n"
|
12 |
+
"Last-Translator: ms-studio <code@ms-studio.net>\n"
|
13 |
+
"Language-Team: \n"
|
14 |
+
"X-Poedit-Language: German\n"
|
15 |
+
"X-Poedit-Country: GERMANY\n"
|
16 |
+
|
17 |
+
#: admin/box-factory.php:56
|
18 |
+
msgid " (from)"
|
19 |
+
msgstr " (von)"
|
20 |
+
|
21 |
+
#: admin/box-factory.php:57
|
22 |
+
msgid " (to)"
|
23 |
+
msgstr " (zu)"
|
24 |
+
|
25 |
+
#: admin/box.php:42
|
26 |
+
msgid "Are you sure you want to delete all connections?"
|
27 |
+
msgstr "Wollen Sie wirklich alle Verbindungen löschen?"
|
28 |
+
|
29 |
+
#: admin/box.php:115
|
30 |
+
msgid "Create connections:"
|
31 |
+
msgstr "Verbindungen erstellen:"
|
32 |
+
|
33 |
+
#: admin/box.php:128
|
34 |
+
msgid "Search"
|
35 |
+
msgstr "Suchen"
|
36 |
+
|
37 |
+
#: admin/box.php:136
|
38 |
+
msgid "View All"
|
39 |
+
msgstr "Alle Verbindungen"
|
40 |
+
|
41 |
+
#: admin/box.php:204
|
42 |
+
msgid "previous"
|
43 |
+
msgstr "vorherige"
|
44 |
+
|
45 |
+
#: admin/box.php:205
|
46 |
+
msgid "next"
|
47 |
+
msgstr "folgende"
|
48 |
+
|
49 |
+
#: admin/box.php:206
|
50 |
+
msgid "of"
|
51 |
+
msgstr "von"
|
52 |
+
|
53 |
+
#: admin/fields.php:16
|
54 |
+
msgid "Create connection"
|
55 |
+
msgstr "Verbindung erstellen"
|
56 |
+
|
57 |
+
#: admin/fields.php:30
|
58 |
+
msgid "Delete all connections"
|
59 |
+
msgstr "Alle Verbindungen löschen"
|
60 |
+
|
61 |
+
#: admin/fields.php:39
|
62 |
+
msgid "Delete connection"
|
63 |
+
msgstr "Verbindung löschen"
|
64 |
+
|
65 |
+
#: scb/AdminPage.php:165
|
66 |
+
msgid "Settings <strong>saved</strong>."
|
67 |
+
msgstr "Einstellungen <strong>gespeichert</strong>"
|
68 |
+
|
69 |
+
#: scb/AdminPage.php:178
|
70 |
+
#: scb/AdminPage.php:189
|
71 |
+
msgid "Save Changes"
|
72 |
+
msgstr "Änderungen speichern"
|
73 |
+
|
74 |
+
#: scb/AdminPage.php:350
|
75 |
+
msgid "Settings"
|
76 |
+
msgstr "Einstellungen"
|
77 |
+
|
78 |
+
#: core/type.php:65
|
79 |
+
msgid "Connected %s"
|
80 |
+
msgstr "Verbundene %s"
|
81 |
+
|
82 |
+
#: core/widget.php:15
|
83 |
+
msgid "Posts 2 Posts"
|
84 |
+
msgstr "Posts 2 Posts"
|
85 |
+
|
86 |
+
#: core/widget.php:16
|
87 |
+
msgid "A list of posts connected to the current post"
|
88 |
+
msgstr "Eine Liste von Artikeln, die mit diesem Artikel verbunden sind"
|
89 |
+
|
90 |
+
#: core/widget.php:37
|
91 |
+
msgid "Connection type:"
|
92 |
+
msgstr "Verbindungs-Typ:"
|
93 |
+
|
94 |
+
#: core/widget.php:41
|
95 |
+
msgid "Connection listing:"
|
96 |
+
msgstr "Verbindungs-Liste:"
|
97 |
+
|
98 |
+
#: core/widget.php:47
|
99 |
+
msgid "connected"
|
100 |
+
msgstr "verbunden"
|
101 |
+
|
102 |
+
#: core/widget.php:48
|
103 |
+
msgid "related"
|
104 |
+
msgstr "verwandt"
|
105 |
+
|
106 |
+
#: core/widget.php:73
|
107 |
+
msgid "Related %s"
|
108 |
+
msgstr "Verwandte %s"
|
109 |
+
|
110 |
+
#: core/storage.php:35
|
111 |
+
msgid "Upgraded %d connections."
|
112 |
+
msgstr "%d Verbindungen wurden ge-upgradet"
|
113 |
+
|
114 |
+
#: core/storage.php:38
|
115 |
+
msgid "The Posts 2 Posts connections need to be upgraded. <a href=\"%s\">Proceed.</a>"
|
116 |
+
msgstr "Die Posts 2 Posts Verbindungen benötigen ein Upgrade. <a href=\"%s\">Ausführen.</a>"
|
117 |
+
|
118 |
+
#: core/side.php:110
|
119 |
+
msgid "Users"
|
120 |
+
msgstr "Benutzer"
|
121 |
+
|
122 |
+
#: core/side.php:115
|
123 |
+
msgid "User"
|
124 |
+
msgstr "Benutzer"
|
125 |
+
|
126 |
+
#: core/side.php:116
|
127 |
+
msgid "Search Users"
|
128 |
+
msgstr "Benutzer suchen"
|
129 |
+
|
130 |
+
#: core/side.php:117
|
131 |
+
msgid "No users found."
|
132 |
+
msgstr "Keine Benutzer gefunden."
|
133 |
+
|
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:
|
11 |
-
"PO-Revision-Date:
|
12 |
"Last-Translator: scribu <mail@scribu.net>\n"
|
13 |
"Language-Team: ROMANIAN <LL@li.org>\n"
|
14 |
"Language: \n"
|
@@ -16,68 +16,83 @@ msgstr ""
|
|
16 |
"Content-Type: text/plain; charset=UTF-8\n"
|
17 |
"Content-Transfer-Encoding: 8bit\n"
|
18 |
|
19 |
-
#: admin/box.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
msgid "Are you sure you want to delete all connections?"
|
21 |
msgstr "Sigur vreți să ștergeți toate conexiunile?"
|
22 |
|
23 |
-
#: admin/box.php:
|
24 |
msgid "Create connections:"
|
25 |
msgstr "Creează conexiuni:"
|
26 |
|
27 |
-
#: admin/box.php:
|
28 |
-
msgid "Search"
|
29 |
-
msgstr "Căutare"
|
30 |
-
|
31 |
-
#: admin/box.php:168
|
32 |
msgid "View All"
|
33 |
msgstr "Vezi toate"
|
34 |
|
35 |
-
#: admin/box.php:
|
|
|
|
|
|
|
|
|
36 |
msgid "previous"
|
37 |
msgstr "anterioare"
|
38 |
|
39 |
-
#: admin/box.php:
|
40 |
msgid "next"
|
41 |
msgstr "următoare"
|
42 |
|
43 |
-
#: admin/box.php:
|
44 |
msgid "of"
|
45 |
msgstr "din"
|
46 |
|
47 |
-
#: admin/
|
|
|
|
|
|
|
|
|
48 |
msgid "Create connection"
|
49 |
msgstr "Crează conexiune"
|
50 |
|
51 |
-
#: admin/fields.php:
|
52 |
msgid "Delete all connections"
|
53 |
msgstr "Șterge toate conexiunile"
|
54 |
|
55 |
-
#: admin/fields.php:
|
56 |
msgid "Delete connection"
|
57 |
msgstr "Șterge conexiune"
|
58 |
|
59 |
-
#:
|
60 |
-
msgid "
|
61 |
-
msgstr "
|
62 |
|
63 |
-
#:
|
64 |
-
|
65 |
-
|
66 |
-
msgstr "Salvează schimbările"
|
67 |
|
68 |
-
#:
|
69 |
-
msgid "
|
70 |
-
msgstr "
|
71 |
|
72 |
-
#: core/
|
73 |
-
msgid "
|
74 |
-
msgstr "
|
75 |
|
76 |
-
#: core/
|
77 |
-
msgid "
|
78 |
-
msgstr "
|
79 |
|
80 |
-
#: core/
|
|
|
|
|
|
|
|
|
81 |
msgid "Connected %s"
|
82 |
msgstr "%s conectate"
|
83 |
|
@@ -89,26 +104,39 @@ msgstr "Posts 2 Posts"
|
|
89 |
msgid "A list of posts connected to the current post"
|
90 |
msgstr "O lista de postări conectate la postarea curentă"
|
91 |
|
92 |
-
#: core/widget.php:
|
93 |
msgid "Connection type:"
|
94 |
msgstr "Tipul conexiunii:"
|
95 |
|
96 |
-
#: core/widget.php:
|
97 |
msgid "Connection listing:"
|
98 |
msgstr "Tipul conexiunii:"
|
99 |
|
100 |
-
#: core/widget.php:
|
101 |
msgid "connected"
|
102 |
msgstr "conectate"
|
103 |
|
104 |
-
#: core/widget.php:
|
105 |
msgid "related"
|
106 |
msgstr "înrudite"
|
107 |
|
108 |
-
#: core/widget.php:
|
109 |
msgid "Related %s"
|
110 |
msgstr "%s înrudite"
|
111 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
#~ msgid "Recent"
|
113 |
#~ msgstr "Recente"
|
114 |
|
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 |
"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"
|
98 |
|
104 |
msgid "A list of posts connected to the current post"
|
105 |
msgstr "O lista de postări conectate la postarea curentă"
|
106 |
|
107 |
+
#: core/widget.php:37
|
108 |
msgid "Connection type:"
|
109 |
msgstr "Tipul conexiunii:"
|
110 |
|
111 |
+
#: core/widget.php:41
|
112 |
msgid "Connection listing:"
|
113 |
msgstr "Tipul conexiunii:"
|
114 |
|
115 |
+
#: core/widget.php:47
|
116 |
msgid "connected"
|
117 |
msgstr "conectate"
|
118 |
|
119 |
+
#: core/widget.php:48
|
120 |
msgid "related"
|
121 |
msgstr "înrudite"
|
122 |
|
123 |
+
#: core/widget.php:73
|
124 |
msgid "Related %s"
|
125 |
msgstr "%s înrudite"
|
126 |
|
127 |
+
#: scb/AdminPage.php:172
|
128 |
+
msgid "Settings <strong>saved</strong>."
|
129 |
+
msgstr "Setări <strong>salvate</strong>."
|
130 |
+
|
131 |
+
#: scb/AdminPage.php:185
|
132 |
+
#: scb/AdminPage.php:196
|
133 |
+
msgid "Save Changes"
|
134 |
+
msgstr "Salvează schimbările"
|
135 |
+
|
136 |
+
#: scb/AdminPage.php:360
|
137 |
+
msgid "Settings"
|
138 |
+
msgstr "Setări"
|
139 |
+
|
140 |
#~ msgid "Recent"
|
141 |
#~ msgstr "Recente"
|
142 |
|
lang/posts-to-posts-sv_SE.mo
ADDED
Binary file
|
lang/posts-to-posts-sv_SE.po
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (C) 2010
|
2 |
+
# This file is distributed under the same license as the package.
|
3 |
+
msgid ""
|
4 |
+
msgstr ""
|
5 |
+
"Project-Id-Version: Posts 2 Posts\n"
|
6 |
+
"Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
|
7 |
+
"POT-Creation-Date: 2011-09-24 13:12:56+00:00\n"
|
8 |
+
"MIME-Version: 1.0\n"
|
9 |
+
"Content-Type: text/plain; charset=utf-8\n"
|
10 |
+
"Content-Transfer-Encoding: 8bit\n"
|
11 |
+
"PO-Revision-Date: 2011-10-17 12:17+0100\n"
|
12 |
+
"Last-Translator: Joel Arvidsson <joel@oblador.se>\n"
|
13 |
+
"Language-Team: \n"
|
14 |
+
"X-Poedit-Language: Swedish\n"
|
15 |
+
"X-Poedit-Country: SWEDEN\n"
|
16 |
+
"X-Poedit-SourceCharset: utf-8\n"
|
17 |
+
|
18 |
+
#: scb/AdminPage.php:163
|
19 |
+
msgid "Settings <strong>saved</strong>."
|
20 |
+
msgstr "Inställningar <strong>sparade</strong>."
|
21 |
+
|
22 |
+
#: scb/AdminPage.php:176
|
23 |
+
#: scb/AdminPage.php:187
|
24 |
+
msgid "Save Changes"
|
25 |
+
msgstr "Spara ändringar"
|
26 |
+
|
27 |
+
#: scb/AdminPage.php:348
|
28 |
+
msgid "Settings"
|
29 |
+
msgstr "Inställningar"
|
30 |
+
|
31 |
+
#: admin/fields.php:13
|
32 |
+
msgid "Create connection"
|
33 |
+
msgstr "Skapa koppling"
|
34 |
+
|
35 |
+
#: admin/fields.php:25
|
36 |
+
msgid "Delete all connections"
|
37 |
+
msgstr "Radera alla kopplingar"
|
38 |
+
|
39 |
+
#: admin/fields.php:34
|
40 |
+
msgid "Delete connection"
|
41 |
+
msgstr "Radera koppling"
|
42 |
+
|
43 |
+
#: admin/box.php:59
|
44 |
+
msgid "Are you sure you want to delete all connections?"
|
45 |
+
msgstr "Är du säker på att du vill radera alla kopplingar?"
|
46 |
+
|
47 |
+
#: admin/box.php:69
|
48 |
+
msgid "Connected %s"
|
49 |
+
msgstr "Kopplad %s"
|
50 |
+
|
51 |
+
#: admin/box.php:116
|
52 |
+
msgid "Create connections:"
|
53 |
+
msgstr "Skapa kopplingar: "
|
54 |
+
|
55 |
+
#: admin/box.php:125
|
56 |
+
msgid "Search"
|
57 |
+
msgstr "Sök"
|
58 |
+
|
59 |
+
#: admin/box.php:133
|
60 |
+
msgid "View All"
|
61 |
+
msgstr "Visa alla"
|
62 |
+
|
63 |
+
#: admin/box.php:216
|
64 |
+
msgid "previous"
|
65 |
+
msgstr "föregående"
|
66 |
+
|
67 |
+
#: admin/box.php:217
|
68 |
+
msgid "next"
|
69 |
+
msgstr "nästa"
|
70 |
+
|
71 |
+
#: admin/box.php:218
|
72 |
+
msgid "of"
|
73 |
+
msgstr "av"
|
74 |
+
|
75 |
+
#: core/widget.php:14
|
76 |
+
msgid "Posts 2 Posts"
|
77 |
+
msgstr ""
|
78 |
+
|
79 |
+
#: core/widget.php:15
|
80 |
+
msgid "A list of posts connected to the current post"
|
81 |
+
msgstr "En lista över inlägg kopplade till aktuellt inlägg"
|
82 |
+
|
83 |
+
#: core/widget.php:29
|
84 |
+
msgid "Connection type:"
|
85 |
+
msgstr "Kopplingstyp: "
|
86 |
+
|
87 |
+
#: core/widget.php:53
|
88 |
+
msgid "Related %s"
|
89 |
+
msgstr "Relaterade %s"
|
90 |
+
|
lang/posts-to-posts-tr_TR.mo
ADDED
Binary file
|
lang/posts-to-posts-tr_TR.po
ADDED
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Translation of the WordPress plugin Posts 2 Posts 1.1.4 by scribu.
|
2 |
+
# Copyright (C) 2011 scribu
|
3 |
+
# This file is distributed under the same license as the Posts 2 Posts package.
|
4 |
+
# ÖNDER CEYLAN <ondercey@yahoo.com>, 2011.
|
5 |
+
#
|
6 |
+
msgid ""
|
7 |
+
msgstr ""
|
8 |
+
"Project-Id-Version: Posts 2 Posts 1.1.4\n"
|
9 |
+
"Report-Msgid-Bugs-To: http://wordpress.org/tag/posts-to-posts\n"
|
10 |
+
"POT-Creation-Date: 2011-03-30 21:56+0300\n"
|
11 |
+
"PO-Revision-Date: 2012-01-23 00:54+0200\n"
|
12 |
+
"Last-Translator: \n"
|
13 |
+
"Language-Team: \n"
|
14 |
+
"Language: \n"
|
15 |
+
"MIME-Version: 1.0\n"
|
16 |
+
"Content-Type: text/plain; charset=UTF-8\n"
|
17 |
+
"Content-Transfer-Encoding: 8bit\n"
|
18 |
+
|
19 |
+
#: admin/box.php:42
|
20 |
+
msgid "Are you sure you want to delete all connections?"
|
21 |
+
msgstr "Tüm bağlantıları kaldırmak istediğinizden emin misiniz?"
|
22 |
+
|
23 |
+
#: admin/box.php:120
|
24 |
+
msgid "Create connections:"
|
25 |
+
msgstr "Bağlantı yarat:"
|
26 |
+
|
27 |
+
#: admin/box.php:133
|
28 |
+
msgid "Search"
|
29 |
+
msgstr "Ara"
|
30 |
+
|
31 |
+
#: admin/box.php:141
|
32 |
+
msgid "View All"
|
33 |
+
msgstr "Tümünü Listele"
|
34 |
+
|
35 |
+
#: admin/box.php:209
|
36 |
+
msgid "previous"
|
37 |
+
msgstr "önceki"
|
38 |
+
|
39 |
+
#: admin/box.php:210
|
40 |
+
msgid "next"
|
41 |
+
msgstr "sonraki"
|
42 |
+
|
43 |
+
#: admin/box.php:211
|
44 |
+
msgid "of"
|
45 |
+
msgstr "arasından"
|
46 |
+
|
47 |
+
#: admin/fields.php:14
|
48 |
+
msgid "Create connection"
|
49 |
+
msgstr "Bağlantı ekle"
|
50 |
+
|
51 |
+
#: admin/fields.php:27
|
52 |
+
msgid "Delete all connections"
|
53 |
+
msgstr "Tüm bağlantıları kaldır"
|
54 |
+
|
55 |
+
#: admin/fields.php:36
|
56 |
+
msgid "Delete connection"
|
57 |
+
msgstr "Bağlantıyı kaldır"
|
58 |
+
|
59 |
+
#: core/side.php:141
|
60 |
+
msgid "Users"
|
61 |
+
msgstr "Kullanıcılar"
|
62 |
+
|
63 |
+
#: core/side.php:146
|
64 |
+
msgid "User"
|
65 |
+
msgstr "Kullanıcı"
|
66 |
+
|
67 |
+
#: core/side.php:147
|
68 |
+
msgid "Search Users"
|
69 |
+
msgstr "Kullanıcı Ara"
|
70 |
+
|
71 |
+
#: core/side.php:148
|
72 |
+
msgid "No users found."
|
73 |
+
msgstr "Kullanıcı bulunamadı."
|
74 |
+
|
75 |
+
#: core/storage.php:35
|
76 |
+
msgid "Upgraded %d connections."
|
77 |
+
msgstr "%d bağlantı güncellendi."
|
78 |
+
|
79 |
+
#: core/storage.php:38
|
80 |
+
msgid "The Posts 2 Posts connections need to be upgraded. <a href='%s'>Proceed.</a>"
|
81 |
+
msgstr "Posts 2 Posts bağlantılarının güncellenmesi gerekiyor. <a href='%s'>Devam et.</a>"
|
82 |
+
|
83 |
+
#: core/type.php:73
|
84 |
+
msgid "Connected %s"
|
85 |
+
msgstr "%s Bağlandı"
|
86 |
+
|
87 |
+
#: core/widget.php:15
|
88 |
+
msgid "Posts 2 Posts"
|
89 |
+
msgstr "Posts 2 Posts"
|
90 |
+
|
91 |
+
#: core/widget.php:16
|
92 |
+
msgid "A list of posts connected to the current post"
|
93 |
+
msgstr "Mevcut sayfayla bağlantılı sayfalar"
|
94 |
+
|
95 |
+
#: core/widget.php:37
|
96 |
+
msgid "Connection type:"
|
97 |
+
msgstr "Bağlantı türü:"
|
98 |
+
|
99 |
+
#: core/widget.php:41
|
100 |
+
msgid "Connection listing:"
|
101 |
+
msgstr "Bağlantı listesi:"
|
102 |
+
|
103 |
+
#: core/widget.php:47
|
104 |
+
msgid "connected"
|
105 |
+
msgstr "bağlı"
|
106 |
+
|
107 |
+
#: core/widget.php:48
|
108 |
+
msgid "related"
|
109 |
+
msgstr "benzer"
|
110 |
+
|
111 |
+
#: core/widget.php:73
|
112 |
+
msgid "Related %s"
|
113 |
+
msgstr "Benzer %s"
|
114 |
+
|
lang/posts-to-posts.pot
CHANGED
@@ -1,78 +1,96 @@
|
|
1 |
-
# Copyright (C)
|
2 |
# This file is distributed under the same license as the package.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
"Project-Id-Version: \n"
|
6 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
|
7 |
-
"POT-Creation-Date:
|
8 |
"MIME-Version: 1.0\n"
|
9 |
"Content-Type: text/plain; charset=UTF-8\n"
|
10 |
"Content-Transfer-Encoding: 8bit\n"
|
11 |
-
"PO-Revision-Date:
|
12 |
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
13 |
"Language-Team: LANGUAGE <LL@li.org>\n"
|
14 |
|
15 |
-
#: admin/box.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
msgid "Are you sure you want to delete all connections?"
|
17 |
msgstr ""
|
18 |
|
19 |
-
#: admin/box.php:
|
20 |
msgid "Create connections:"
|
21 |
msgstr ""
|
22 |
|
23 |
-
#: admin/box.php:
|
24 |
-
msgid "
|
25 |
msgstr ""
|
26 |
|
27 |
-
#: admin/box.php:
|
28 |
-
msgid "
|
29 |
msgstr ""
|
30 |
|
31 |
-
#: admin/box.php:
|
32 |
msgid "previous"
|
33 |
msgstr ""
|
34 |
|
35 |
-
#: admin/box.php:
|
36 |
msgid "next"
|
37 |
msgstr ""
|
38 |
|
39 |
-
#: admin/box.php:
|
40 |
msgid "of"
|
41 |
msgstr ""
|
42 |
|
43 |
-
#: admin/
|
|
|
|
|
|
|
|
|
44 |
msgid "Create connection"
|
45 |
msgstr ""
|
46 |
|
47 |
-
#: admin/fields.php:
|
48 |
msgid "Delete all connections"
|
49 |
msgstr ""
|
50 |
|
51 |
-
#: admin/fields.php:
|
52 |
msgid "Delete connection"
|
53 |
msgstr ""
|
54 |
|
55 |
-
#:
|
56 |
-
msgid "
|
57 |
msgstr ""
|
58 |
|
59 |
-
#:
|
60 |
-
msgid "
|
61 |
msgstr ""
|
62 |
|
63 |
-
#:
|
64 |
-
msgid "
|
65 |
msgstr ""
|
66 |
|
67 |
-
#: core/
|
68 |
-
msgid "
|
69 |
msgstr ""
|
70 |
|
71 |
-
#: core/
|
72 |
-
msgid "
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
msgstr ""
|
74 |
|
75 |
-
#: core/type.php:
|
76 |
msgid "Connected %s"
|
77 |
msgstr ""
|
78 |
|
@@ -84,22 +102,34 @@ msgstr ""
|
|
84 |
msgid "A list of posts connected to the current post"
|
85 |
msgstr ""
|
86 |
|
87 |
-
#: core/widget.php:
|
88 |
msgid "Connection type:"
|
89 |
msgstr ""
|
90 |
|
91 |
-
#: core/widget.php:
|
92 |
msgid "Connection listing:"
|
93 |
msgstr ""
|
94 |
|
95 |
-
#: core/widget.php:
|
96 |
msgid "connected"
|
97 |
msgstr ""
|
98 |
|
99 |
-
#: core/widget.php:
|
100 |
msgid "related"
|
101 |
msgstr ""
|
102 |
|
103 |
-
#: core/widget.php:
|
104 |
msgid "Related %s"
|
105 |
msgstr ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright (C) 2012
|
2 |
# This file is distributed under the same license as the package.
|
3 |
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"
|
11 |
+
"PO-Revision-Date: 2012-MO-DA HO:MI+ZONE\n"
|
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
|
94 |
msgid "Connected %s"
|
95 |
msgstr ""
|
96 |
|
102 |
msgid "A list of posts connected to the current post"
|
103 |
msgstr ""
|
104 |
|
105 |
+
#: core/widget.php:37
|
106 |
msgid "Connection type:"
|
107 |
msgstr ""
|
108 |
|
109 |
+
#: core/widget.php:41
|
110 |
msgid "Connection listing:"
|
111 |
msgstr ""
|
112 |
|
113 |
+
#: core/widget.php:47
|
114 |
msgid "connected"
|
115 |
msgstr ""
|
116 |
|
117 |
+
#: core/widget.php:48
|
118 |
msgid "related"
|
119 |
msgstr ""
|
120 |
|
121 |
+
#: core/widget.php:73
|
122 |
msgid "Related %s"
|
123 |
msgstr ""
|
124 |
+
|
125 |
+
#: scb/AdminPage.php:172
|
126 |
+
msgid "Settings <strong>saved</strong>."
|
127 |
+
msgstr ""
|
128 |
+
|
129 |
+
#: scb/AdminPage.php:185 scb/AdminPage.php:196
|
130 |
+
msgid "Save Changes"
|
131 |
+
msgstr ""
|
132 |
+
|
133 |
+
#: scb/AdminPage.php:360
|
134 |
+
msgid "Settings"
|
135 |
+
msgstr ""
|
mustache/Mustache.php
CHANGED
@@ -14,7 +14,7 @@
|
|
14 |
*/
|
15 |
class Mustache {
|
16 |
|
17 |
-
const VERSION = '0.
|
18 |
const SPEC_VERSION = '1.1.2';
|
19 |
|
20 |
/**
|
@@ -90,9 +90,18 @@ class Mustache {
|
|
90 |
* // opening and closing delimiters, as an array or a space-separated string
|
91 |
* 'delimiters' => '<% %>',
|
92 |
*
|
93 |
-
* // an array of pragmas to enable
|
94 |
* 'pragmas' => array(
|
95 |
-
* Mustache::PRAGMA_UNESCAPED
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
* ),
|
97 |
* );
|
98 |
*
|
@@ -132,13 +141,19 @@ class Mustache {
|
|
132 |
}
|
133 |
|
134 |
if (isset($options['pragmas'])) {
|
135 |
-
foreach ($options['pragmas'] as $pragma_name) {
|
136 |
-
if (!in_array($pragma_name, $this->_pragmasImplemented)) {
|
137 |
throw new MustacheException('Unknown pragma: ' . $pragma_name, MustacheException::UNKNOWN_PRAGMA);
|
138 |
}
|
139 |
}
|
140 |
$this->_pragmas = $options['pragmas'];
|
141 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
}
|
143 |
|
144 |
/**
|
@@ -189,7 +204,7 @@ class Mustache {
|
|
189 |
}
|
190 |
|
191 |
$template = $this->_renderPragmas($template);
|
192 |
-
$template = $this->_renderTemplate($template
|
193 |
|
194 |
$this->_otag = $otag_orig;
|
195 |
$this->_ctag = $ctag_orig;
|
@@ -403,7 +418,11 @@ class Mustache {
|
|
403 |
$options_string = $matches['options_string'];
|
404 |
|
405 |
if (!in_array($pragma_name, $this->_pragmasImplemented)) {
|
406 |
-
|
|
|
|
|
|
|
|
|
407 |
}
|
408 |
|
409 |
$options = array();
|
@@ -448,7 +467,9 @@ class Mustache {
|
|
448 |
*/
|
449 |
protected function _getPragmaOptions($pragma_name) {
|
450 |
if (!$this->_hasPragma($pragma_name)) {
|
451 |
-
|
|
|
|
|
452 |
}
|
453 |
|
454 |
return (is_array($this->_localPragmas[$pragma_name])) ? $this->_localPragmas[$pragma_name] : array();
|
@@ -767,7 +788,7 @@ class Mustache {
|
|
767 |
$first = array_shift($chunks);
|
768 |
|
769 |
$ret = $this->_findVariableInContext($first, $this->_context);
|
770 |
-
|
771 |
// Slice off a chunk of context for dot notation traversal.
|
772 |
$c = array($ret);
|
773 |
$ret = $this->_findVariableInContext($next, $c);
|
@@ -819,10 +840,7 @@ class Mustache {
|
|
819 |
* @return string
|
820 |
*/
|
821 |
protected function _getPartial($tag_name) {
|
822 |
-
if (
|
823 |
-
(is_array($this->_partials) || $this->_partials instanceof ArrayAccess)
|
824 |
-
&& isset($this->_partials[$tag_name])
|
825 |
-
) {
|
826 |
return $this->_partials[$tag_name];
|
827 |
}
|
828 |
|
14 |
*/
|
15 |
class Mustache {
|
16 |
|
17 |
+
const VERSION = '1.0.0';
|
18 |
const SPEC_VERSION = '1.1.2';
|
19 |
|
20 |
/**
|
90 |
* // opening and closing delimiters, as an array or a space-separated string
|
91 |
* 'delimiters' => '<% %>',
|
92 |
*
|
93 |
+
* // an array of pragmas to enable/disable
|
94 |
* 'pragmas' => array(
|
95 |
+
* Mustache::PRAGMA_UNESCAPED => true
|
96 |
+
* ),
|
97 |
+
*
|
98 |
+
* // an array of thrown exceptions to enable/disable
|
99 |
+
* 'throws_exceptions' => array(
|
100 |
+
* MustacheException::UNKNOWN_VARIABLE => false,
|
101 |
+
* MustacheException::UNCLOSED_SECTION => true,
|
102 |
+
* MustacheException::UNEXPECTED_CLOSE_SECTION => true,
|
103 |
+
* MustacheException::UNKNOWN_PARTIAL => false,
|
104 |
+
* MustacheException::UNKNOWN_PRAGMA => true,
|
105 |
* ),
|
106 |
* );
|
107 |
*
|
141 |
}
|
142 |
|
143 |
if (isset($options['pragmas'])) {
|
144 |
+
foreach ($options['pragmas'] as $pragma_name => $pragma_value) {
|
145 |
+
if (!in_array($pragma_name, $this->_pragmasImplemented, true)) {
|
146 |
throw new MustacheException('Unknown pragma: ' . $pragma_name, MustacheException::UNKNOWN_PRAGMA);
|
147 |
}
|
148 |
}
|
149 |
$this->_pragmas = $options['pragmas'];
|
150 |
}
|
151 |
+
|
152 |
+
if (isset($options['throws_exceptions'])) {
|
153 |
+
foreach ($options['throws_exceptions'] as $exception => $value) {
|
154 |
+
$this->_throwsExceptions[$exception] = $value;
|
155 |
+
}
|
156 |
+
}
|
157 |
}
|
158 |
|
159 |
/**
|
204 |
}
|
205 |
|
206 |
$template = $this->_renderPragmas($template);
|
207 |
+
$template = $this->_renderTemplate($template);
|
208 |
|
209 |
$this->_otag = $otag_orig;
|
210 |
$this->_ctag = $ctag_orig;
|
418 |
$options_string = $matches['options_string'];
|
419 |
|
420 |
if (!in_array($pragma_name, $this->_pragmasImplemented)) {
|
421 |
+
if ($this->_throwsException(MustacheException::UNKNOWN_PRAGMA)) {
|
422 |
+
throw new MustacheException('Unknown pragma: ' . $pragma_name, MustacheException::UNKNOWN_PRAGMA);
|
423 |
+
} else {
|
424 |
+
return '';
|
425 |
+
}
|
426 |
}
|
427 |
|
428 |
$options = array();
|
467 |
*/
|
468 |
protected function _getPragmaOptions($pragma_name) {
|
469 |
if (!$this->_hasPragma($pragma_name)) {
|
470 |
+
if ($this->_throwsException(MustacheException::UNKNOWN_PRAGMA)) {
|
471 |
+
throw new MustacheException('Unknown pragma: ' . $pragma_name, MustacheException::UNKNOWN_PRAGMA);
|
472 |
+
}
|
473 |
}
|
474 |
|
475 |
return (is_array($this->_localPragmas[$pragma_name])) ? $this->_localPragmas[$pragma_name] : array();
|
788 |
$first = array_shift($chunks);
|
789 |
|
790 |
$ret = $this->_findVariableInContext($first, $this->_context);
|
791 |
+
foreach ($chunks as $next) {
|
792 |
// Slice off a chunk of context for dot notation traversal.
|
793 |
$c = array($ret);
|
794 |
$ret = $this->_findVariableInContext($next, $c);
|
840 |
* @return string
|
841 |
*/
|
842 |
protected function _getPartial($tag_name) {
|
843 |
+
if ((is_array($this->_partials) || $this->_partials instanceof ArrayAccess) && isset($this->_partials[$tag_name])) {
|
|
|
|
|
|
|
844 |
return $this->_partials[$tag_name];
|
845 |
}
|
846 |
|
mustache/README.markdown
CHANGED
@@ -9,73 +9,79 @@ Usage
|
|
9 |
|
10 |
A quick example:
|
11 |
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
|
|
18 |
|
19 |
|
20 |
And a more in-depth example--this is the canonical Mustache template:
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
|
|
|
|
27 |
|
28 |
|
29 |
Along with the associated Mustache class:
|
30 |
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
|
|
35 |
|
36 |
-
|
37 |
-
|
38 |
-
}
|
39 |
-
|
40 |
-
public $in_ca = true;
|
41 |
}
|
42 |
|
|
|
|
|
|
|
|
|
43 |
|
44 |
Render it like so:
|
45 |
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
|
|
50 |
|
51 |
|
52 |
Here's the same thing, a different way:
|
53 |
|
54 |
Create a view object--which could also be an associative array, but those don't do functions quite as well:
|
55 |
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
public function taxed_value() {
|
62 |
-
return $this->value - ($this->value * 0.4);
|
63 |
-
}
|
64 |
-
|
65 |
-
public $in_ca = true;
|
66 |
-
}
|
67 |
-
?>
|
68 |
|
|
|
|
|
|
|
69 |
|
70 |
-
|
|
|
|
|
71 |
|
72 |
-
<?php
|
73 |
-
$chris = new Chris;
|
74 |
-
$m = new Mustache;
|
75 |
-
echo $m->render($template, $chris);
|
76 |
-
?>
|
77 |
|
|
|
78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
|
80 |
|
81 |
Known Issues
|
9 |
|
10 |
A quick example:
|
11 |
|
12 |
+
```php
|
13 |
+
<?php
|
14 |
+
include('Mustache.php');
|
15 |
+
$m = new Mustache;
|
16 |
+
echo $m->render('Hello {{planet}}', array('planet' => 'World!'));
|
17 |
+
// "Hello World!"
|
18 |
+
```
|
19 |
|
20 |
|
21 |
And a more in-depth example--this is the canonical Mustache template:
|
22 |
|
23 |
+
```
|
24 |
+
Hello {{name}}
|
25 |
+
You have just won ${{value}}!
|
26 |
+
{{#in_ca}}
|
27 |
+
Well, ${{taxed_value}}, after taxes.
|
28 |
+
{{/in_ca}}
|
29 |
+
```
|
30 |
|
31 |
|
32 |
Along with the associated Mustache class:
|
33 |
|
34 |
+
```php
|
35 |
+
<?php
|
36 |
+
class Chris extends Mustache {
|
37 |
+
public $name = "Chris";
|
38 |
+
public $value = 10000;
|
39 |
|
40 |
+
public function taxed_value() {
|
41 |
+
return $this->value - ($this->value * 0.4);
|
|
|
|
|
|
|
42 |
}
|
43 |
|
44 |
+
public $in_ca = true;
|
45 |
+
}
|
46 |
+
```
|
47 |
+
|
48 |
|
49 |
Render it like so:
|
50 |
|
51 |
+
```php
|
52 |
+
<?php
|
53 |
+
$chris = new Chris;
|
54 |
+
echo $chris->render($template);
|
55 |
+
```
|
56 |
|
57 |
|
58 |
Here's the same thing, a different way:
|
59 |
|
60 |
Create a view object--which could also be an associative array, but those don't do functions quite as well:
|
61 |
|
62 |
+
```php
|
63 |
+
<?php
|
64 |
+
class Chris {
|
65 |
+
public $name = "Chris";
|
66 |
+
public $value = 10000;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
|
68 |
+
public function taxed_value() {
|
69 |
+
return $this->value - ($this->value * 0.4);
|
70 |
+
}
|
71 |
|
72 |
+
public $in_ca = true;
|
73 |
+
}
|
74 |
+
```
|
75 |
|
|
|
|
|
|
|
|
|
|
|
76 |
|
77 |
+
And render it:
|
78 |
|
79 |
+
```php
|
80 |
+
<?php
|
81 |
+
$chris = new Chris;
|
82 |
+
$m = new Mustache;
|
83 |
+
echo $m->render($template, $chris);
|
84 |
+
```
|
85 |
|
86 |
|
87 |
Known Issues
|
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.
|
6 |
Author: scribu
|
7 |
Author URI: http://scribu.net/
|
8 |
Plugin URI: http://scribu.net/wordpress/posts-to-posts
|
@@ -10,7 +10,7 @@ Text Domain: posts-to-posts
|
|
10 |
Domain Path: /lang
|
11 |
|
12 |
|
13 |
-
Copyright (C) 2010-
|
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
|
@@ -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.
|
30 |
|
31 |
define( 'P2P_TEXTDOMAIN', 'posts-to-posts' );
|
32 |
|
@@ -38,12 +38,12 @@ function _p2p_init() {
|
|
38 |
load_plugin_textdomain( P2P_TEXTDOMAIN, '', basename( $base ) . '/lang' );
|
39 |
|
40 |
_p2p_load_files( "$base/core", array(
|
41 |
-
'storage', 'query', 'url-query',
|
42 |
-
'util', 'type', '
|
43 |
'api', 'widget'
|
44 |
) );
|
45 |
|
46 |
-
P2P_Widget::init(
|
47 |
|
48 |
if ( is_admin() ) {
|
49 |
_p2p_load_files( "$base/admin", array(
|
@@ -52,6 +52,8 @@ function _p2p_init() {
|
|
52 |
'column-factory', 'column'
|
53 |
) );
|
54 |
}
|
|
|
|
|
55 |
}
|
56 |
scb_init( '_p2p_init' );
|
57 |
|
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
|
10 |
Domain Path: /lang
|
11 |
|
12 |
|
13 |
+
Copyright (C) 2010-2012 Cristi Burcă (mail@scribu.net)
|
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
|
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 |
|
38 |
load_plugin_textdomain( P2P_TEXTDOMAIN, '', basename( $base ) . '/lang' );
|
39 |
|
40 |
_p2p_load_files( "$base/core", array(
|
41 |
+
'storage', 'query', 'query-post', 'query-user', 'url-query',
|
42 |
+
'util', 'side', 'type-factory', 'type', 'directed-type',
|
43 |
'api', 'widget'
|
44 |
) );
|
45 |
|
46 |
+
P2P_Widget::init();
|
47 |
|
48 |
if ( is_admin() ) {
|
49 |
_p2p_load_files( "$base/admin", array(
|
52 |
'column-factory', 'column'
|
53 |
) );
|
54 |
}
|
55 |
+
|
56 |
+
register_uninstall_hook( __FILE__, array( 'P2P_Storage', 'uninstall' ) );
|
57 |
}
|
58 |
scb_init( '_p2p_init' );
|
59 |
|
readme.txt
CHANGED
@@ -1,22 +1,25 @@
|
|
1 |
=== Posts 2 Posts ===
|
2 |
Contributors: scribu, ciobi
|
3 |
-
Tags:
|
4 |
Requires at least: 3.2
|
5 |
Tested up to: 3.3
|
6 |
-
Stable tag: 1.
|
7 |
|
8 |
-
|
9 |
|
10 |
== Description ==
|
11 |
|
12 |
-
This plugin allows you to create many-to-many relationships between posts of any type: post, page, custom etc.
|
13 |
-
|
14 |
-
A few example use cases:
|
15 |
|
16 |
* post series
|
17 |
* manually curated lists of related posts
|
18 |
* 'actor' posts connected to 'movie' posts
|
19 |
|
|
|
|
|
|
|
|
|
|
|
20 |
etc.
|
21 |
|
22 |
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)
|
@@ -47,6 +50,51 @@ Make sure your host is running PHP 5. The only foolproof way to do this is to ad
|
|
47 |
|
48 |
== Changelog ==
|
49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
= 1.0.1 =
|
51 |
* don't show metabox at all if user doesn't have the required capability
|
52 |
* fix checkbox handling when there are no other input fields
|
1 |
=== Posts 2 Posts ===
|
2 |
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 |
|
10 |
== Description ==
|
11 |
|
12 |
+
This plugin allows you to create many-to-many relationships between posts of any type: post, page, custom etc. A few example use cases:
|
|
|
|
|
13 |
|
14 |
* post series
|
15 |
* manually curated lists of related posts
|
16 |
* 'actor' posts connected to 'movie' posts
|
17 |
|
18 |
+
Additionally, you can create many-to-many relationships between posts and users. So, you could also implement:
|
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)
|
50 |
|
51 |
== Changelog ==
|
52 |
|
53 |
+
= 1.1.6 =
|
54 |
+
* convert "View All" tab into button
|
55 |
+
* refresh candidate list after deleting a connection
|
56 |
+
* fix cardinality check
|
57 |
+
* introduce 'p2p_connection_type_args' filter
|
58 |
+
* make 'connected_type' accept an array of connection type names
|
59 |
+
* inadvertently remove support for queries without 'connected_type' parameter
|
60 |
+
|
61 |
+
= 1.1.5 =
|
62 |
+
* added P2P_Connection_Type->replace() method
|
63 |
+
* added 'self_connections' flag to p2p_register_connection_type()
|
64 |
+
* made P2P_Connection_Type->each_connected() work for posts-to-users connections
|
65 |
+
* made admin list table columns work for posts-to-users connections
|
66 |
+
* fixed 'from_labels' and 'to_labels' parameters
|
67 |
+
* fixed search being limited only to post titles
|
68 |
+
|
69 |
+
= 1.1.4 =
|
70 |
+
* show attachment thumbnail instead of title
|
71 |
+
* merged 'from_object' into 'from' and 'to_object' into 'to'
|
72 |
+
* made posts-to-users queries respect 'to_query_vars' args
|
73 |
+
* added $prop_name parameter to P2P_Type::each_connected()
|
74 |
+
* fixed connection field name conflict
|
75 |
+
|
76 |
+
= 1.1.3 =
|
77 |
+
* fixed regression related to posts-to-users direction
|
78 |
+
* fixed admin columns overwriting each other
|
79 |
+
* fixed incorrect direction in admin column links
|
80 |
+
* added notices when connection type is not properly defined
|
81 |
+
|
82 |
+
= 1.1.2 =
|
83 |
+
* fixed fields not being saved for posts-to-users connections
|
84 |
+
* fixed missing "New Post" tab in admin box
|
85 |
+
* fixed notice when deleting post
|
86 |
+
|
87 |
+
= 1.1.1 =
|
88 |
+
* fixed faulty scbFramework loading
|
89 |
+
* simplified syntax for defining posts-to-users connection types
|
90 |
+
|
91 |
+
= 1.1 =
|
92 |
+
* add p2p_type column to the wp_p2p table
|
93 |
+
* new low-level api: p2p_create_connection(), p2p_get_connections(), p2p_delete_connections(), p2p_connection_exists()
|
94 |
+
* support posts-to-users and users-to-posts connection types in the admin
|
95 |
+
* add 'from_labels' and 'to_labels' args to p2p_register_connection_type()
|
96 |
+
* [more info](http://scribu.net/wordpress/posts-to-posts/p2p-1-1.html)
|
97 |
+
|
98 |
= 1.0.1 =
|
99 |
* don't show metabox at all if user doesn't have the required capability
|
100 |
* fix checkbox handling when there are no other input fields
|
scb/AdminPage.php
CHANGED
@@ -80,13 +80,10 @@ abstract class scbAdminPage {
|
|
80 |
|
81 |
|
82 |
// Constructor
|
83 |
-
function __construct( $file, $options =
|
84 |
if ( is_a( $options, 'scbOptions' ) )
|
85 |
$this->options = $options;
|
86 |
|
87 |
-
$this->file = $file;
|
88 |
-
$this->plugin_url = plugin_dir_url( $file );
|
89 |
-
|
90 |
$this->setup();
|
91 |
$this->check_args();
|
92 |
|
@@ -99,13 +96,25 @@ abstract class scbAdminPage {
|
|
99 |
add_action( 'admin_menu', array( $this, 'page_init' ), $this->args['admin_action_priority'] );
|
100 |
add_filter( 'contextual_help', array( $this, '_contextual_help' ), 10, 2 );
|
101 |
|
102 |
-
if ( $
|
103 |
-
|
|
|
|
|
|
|
|
|
|
|
104 |
}
|
105 |
|
106 |
// This is where all the page args can be set
|
107 |
function setup(){}
|
108 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
109 |
// This is where the css and js go
|
110 |
// Both wp_enqueue_*() and inline code can be added
|
111 |
function page_head(){}
|
@@ -162,7 +171,7 @@ abstract class scbAdminPage {
|
|
162 |
if ( empty( $msg ) )
|
163 |
$msg = __( 'Settings <strong>saved</strong>.', $this->textdomain );
|
164 |
|
165 |
-
echo
|
166 |
}
|
167 |
|
168 |
|
@@ -187,18 +196,19 @@ abstract class scbAdminPage {
|
|
187 |
$value = __( 'Save Changes', $this->textdomain );
|
188 |
}
|
189 |
|
190 |
-
$input_args = array(
|
191 |
-
'
|
192 |
-
'
|
|
|
193 |
'extra' => '',
|
194 |
-
'desc' => false
|
|
|
|
|
195 |
|
196 |
if ( ! empty( $class ) )
|
197 |
-
$input_args['extra'] =
|
198 |
-
|
199 |
-
$output = "<p class='submit'>\n" . scbForms::input( $input_args ) . "</p>\n";
|
200 |
|
201 |
-
return $
|
202 |
}
|
203 |
|
204 |
/*
|
@@ -319,6 +329,8 @@ abstract class scbAdminPage {
|
|
319 |
if ( ! $this->pagehook )
|
320 |
return;
|
321 |
|
|
|
|
|
322 |
if ( $ajax_submit ) {
|
323 |
$this->ajax_response();
|
324 |
add_action( 'admin_footer', array( $this, 'ajax_submit' ), 20 );
|
80 |
|
81 |
|
82 |
// Constructor
|
83 |
+
function __construct( $file = false, $options = null ) {
|
84 |
if ( is_a( $options, 'scbOptions' ) )
|
85 |
$this->options = $options;
|
86 |
|
|
|
|
|
|
|
87 |
$this->setup();
|
88 |
$this->check_args();
|
89 |
|
96 |
add_action( 'admin_menu', array( $this, 'page_init' ), $this->args['admin_action_priority'] );
|
97 |
add_filter( 'contextual_help', array( $this, '_contextual_help' ), 10, 2 );
|
98 |
|
99 |
+
if ( $file ) {
|
100 |
+
$this->file = $file;
|
101 |
+
$this->plugin_url = plugin_dir_url( $file );
|
102 |
+
|
103 |
+
if ( $this->args['action_link'] )
|
104 |
+
add_filter( 'plugin_action_links_' . plugin_basename( $file ), array( $this, '_action_link' ) );
|
105 |
+
}
|
106 |
}
|
107 |
|
108 |
// This is where all the page args can be set
|
109 |
function setup(){}
|
110 |
|
111 |
+
/**
|
112 |
+
* Called when the page is loaded, but before any rendering.
|
113 |
+
*
|
114 |
+
* Useful for calling $screen->add_help_tab() etc.
|
115 |
+
*/
|
116 |
+
function page_loaded() {}
|
117 |
+
|
118 |
// This is where the css and js go
|
119 |
// Both wp_enqueue_*() and inline code can be added
|
120 |
function page_head(){}
|
171 |
if ( empty( $msg ) )
|
172 |
$msg = __( 'Settings <strong>saved</strong>.', $this->textdomain );
|
173 |
|
174 |
+
echo scb_admin_notice( $msg, $class );
|
175 |
}
|
176 |
|
177 |
|
196 |
$value = __( 'Save Changes', $this->textdomain );
|
197 |
}
|
198 |
|
199 |
+
$input_args = array(
|
200 |
+
'type' => 'submit',
|
201 |
+
'name' => $action,
|
202 |
+
'value' => $value,
|
203 |
'extra' => '',
|
204 |
+
'desc' => false,
|
205 |
+
'wrap' => html( 'p class="submit"', scbForms::TOKEN )
|
206 |
+
);
|
207 |
|
208 |
if ( ! empty( $class ) )
|
209 |
+
$input_args['extra'] = compact( 'class' );
|
|
|
|
|
210 |
|
211 |
+
return scbForms::input( $input_args );
|
212 |
}
|
213 |
|
214 |
/*
|
329 |
if ( ! $this->pagehook )
|
330 |
return;
|
331 |
|
332 |
+
add_action( 'load-' . $this->pagehook, array( $this, 'page_loaded' ) );
|
333 |
+
|
334 |
if ( $ajax_submit ) {
|
335 |
$this->ajax_response();
|
336 |
add_action( 'admin_footer', array( $this, 'ajax_submit' ), 20 );
|
scb/BoxesPage.php
CHANGED
@@ -11,10 +11,9 @@ abstract class scbBoxesPage extends scbAdminPage {
|
|
11 |
*/
|
12 |
protected $boxes = array();
|
13 |
|
14 |
-
function __construct( $file, $options = null ) {
|
15 |
parent::__construct( $file, $options );
|
16 |
|
17 |
-
// too late
|
18 |
scbUtil::add_uninstall_hook( $this->file, array( $this, 'uninstall' ) );
|
19 |
}
|
20 |
|
@@ -167,8 +166,11 @@ abstract class scbBoxesPage extends scbAdminPage {
|
|
167 |
) );
|
168 |
|
169 |
$registered = array();
|
170 |
-
foreach( $this->boxes as $box_args ) {
|
171 |
-
|
|
|
|
|
|
|
172 |
|
173 |
if ( empty( $title ) )
|
174 |
$title = ucfirst( $name );
|
11 |
*/
|
12 |
protected $boxes = array();
|
13 |
|
14 |
+
function __construct( $file = false, $options = null ) {
|
15 |
parent::__construct( $file, $options );
|
16 |
|
|
|
17 |
scbUtil::add_uninstall_hook( $this->file, array( $this, 'uninstall' ) );
|
18 |
}
|
19 |
|
166 |
) );
|
167 |
|
168 |
$registered = array();
|
169 |
+
foreach ( $this->boxes as $box_args ) {
|
170 |
+
foreach ( array( 'name', 'title', 'context', 'priority', 'args' ) as $i => $arg ) {
|
171 |
+
if ( isset( $box_args[$i] ) )
|
172 |
+
$$arg = $box_args[$i];
|
173 |
+
}
|
174 |
|
175 |
if ( empty( $title ) )
|
176 |
$title = ucfirst( $name );
|
scb/Cron.php
CHANGED
@@ -19,7 +19,7 @@ class scbCron {
|
|
19 |
string $schedule OR number $interval
|
20 |
array $callback_args (optional)
|
21 |
*/
|
22 |
-
function __construct( $file, $args ) {
|
23 |
extract( $args, EXTR_SKIP );
|
24 |
|
25 |
// Set time & schedule
|
19 |
string $schedule OR number $interval
|
20 |
array $callback_args (optional)
|
21 |
*/
|
22 |
+
function __construct( $file = false, $args ) {
|
23 |
extract( $args, EXTR_SKIP );
|
24 |
|
25 |
// Set time & schedule
|
scb/Forms.php
CHANGED
@@ -4,35 +4,51 @@
|
|
4 |
|
5 |
class scbForms {
|
6 |
|
7 |
-
const
|
8 |
|
9 |
protected static $cur_name;
|
10 |
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
}
|
20 |
}
|
21 |
|
22 |
-
|
|
|
|
|
|
|
|
|
23 |
$form = new scbForm( $formdata );
|
24 |
return $form->input( $args );
|
25 |
}
|
26 |
|
27 |
-
if ( empty( $args['name'] ) )
|
28 |
return trigger_error( 'Empty name', E_USER_WARNING );
|
|
|
29 |
|
30 |
$args = wp_parse_args( $args, array(
|
31 |
'desc' => '',
|
32 |
-
'desc_pos' => '',
|
|
|
33 |
) );
|
34 |
|
35 |
-
|
|
|
|
|
|
|
36 |
|
37 |
if ( isset( $args['extra'] ) && !is_array( $args['extra'] ) )
|
38 |
$args['extra'] = shortcode_parse_atts( $args['extra'] );
|
@@ -42,20 +58,19 @@ class scbForms {
|
|
42 |
switch ( $args['type'] ) {
|
43 |
case 'select':
|
44 |
case 'radio':
|
45 |
-
|
46 |
-
return trigger_error( "'value' argument is expected to be an array", E_USER_WARNING );
|
47 |
-
|
48 |
-
return self::_single_choice( $args );
|
49 |
break;
|
50 |
case 'checkbox':
|
51 |
-
if ( $
|
52 |
-
|
53 |
else
|
54 |
-
|
55 |
break;
|
56 |
default:
|
57 |
-
|
58 |
}
|
|
|
|
|
59 |
}
|
60 |
|
61 |
|
@@ -168,7 +183,7 @@ class scbForms {
|
|
168 |
$checked = array();
|
169 |
|
170 |
$opts = '';
|
171 |
-
foreach ( $
|
172 |
if ( empty( $value ) || empty( $title ) )
|
173 |
continue;
|
174 |
|
@@ -177,21 +192,22 @@ class scbForms {
|
|
177 |
'value' => $value,
|
178 |
'checked' => in_array( $value, $checked ),
|
179 |
'desc' => $title,
|
180 |
-
'desc_pos' =>
|
181 |
) );
|
182 |
}
|
183 |
|
184 |
-
return $opts;
|
185 |
}
|
186 |
|
187 |
private static function _expand_values( &$args ) {
|
188 |
-
$
|
189 |
|
190 |
-
if ( !empty( $
|
191 |
if ( is_array( $args['desc'] ) ) {
|
192 |
-
$
|
193 |
-
|
194 |
-
|
|
|
195 |
}
|
196 |
}
|
197 |
}
|
@@ -200,11 +216,12 @@ class scbForms {
|
|
200 |
extract( $args );
|
201 |
|
202 |
if ( array( 'foo' ) == $selected ) {
|
203 |
-
|
|
|
204 |
}
|
205 |
|
206 |
$opts = '';
|
207 |
-
foreach ( $
|
208 |
if ( empty( $value ) || empty( $title ) )
|
209 |
continue;
|
210 |
|
@@ -213,11 +230,11 @@ class scbForms {
|
|
213 |
'value' => $value,
|
214 |
'checked' => ( (string) $value == (string) $selected ),
|
215 |
'desc' => $title,
|
216 |
-
'desc_pos' =>
|
217 |
) );
|
218 |
}
|
219 |
|
220 |
-
return $opts;
|
221 |
}
|
222 |
|
223 |
private static function _select( $args ) {
|
@@ -236,7 +253,7 @@ class scbForms {
|
|
236 |
);
|
237 |
}
|
238 |
|
239 |
-
foreach ( $
|
240 |
if ( empty( $value ) || empty( $title ) )
|
241 |
continue;
|
242 |
|
@@ -322,27 +339,17 @@ class scbForms {
|
|
322 |
}
|
323 |
|
324 |
private static function add_label( $input, $desc, $desc_pos ) {
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
$label = '';
|
329 |
-
if ( false === strpos( $desc, self::token ) ) {
|
330 |
-
switch ( $desc_pos ) {
|
331 |
-
case 'before': $label = $desc . ' ' . self::token; break;
|
332 |
-
case 'after': $label = self::token . ' ' . $desc;
|
333 |
-
}
|
334 |
-
} else {
|
335 |
-
$label = $desc;
|
336 |
-
}
|
337 |
-
|
338 |
-
$label = trim( str_replace( self::token, $input, $label ) );
|
339 |
|
|
|
340 |
if ( empty( $desc ) )
|
341 |
-
|
342 |
-
else
|
343 |
-
$output = html( 'label', $label );
|
344 |
|
345 |
-
|
|
|
|
|
|
|
346 |
}
|
347 |
|
348 |
|
@@ -388,12 +395,102 @@ class scbForms {
|
|
388 |
return $value;
|
389 |
}
|
390 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
391 |
private static function is_associative( $array ) {
|
392 |
$keys = array_keys( $array );
|
393 |
return array_keys( $keys ) !== $keys;
|
394 |
}
|
395 |
}
|
396 |
|
|
|
397 |
/**
|
398 |
* A wrapper for scbForms, containing the formdata
|
399 |
*/
|
@@ -418,30 +515,15 @@ class scbForm {
|
|
418 |
}
|
419 |
|
420 |
function input( $args ) {
|
421 |
-
$
|
422 |
|
423 |
-
|
424 |
-
switch ( $args['type'] ) {
|
425 |
-
case 'select':
|
426 |
-
case 'radio':
|
427 |
-
$args['selected'] = $value;
|
428 |
-
break;
|
429 |
-
case 'checkbox':
|
430 |
-
if ( is_array( $value ) )
|
431 |
-
$args['checked'] = $value;
|
432 |
-
else
|
433 |
-
$args['checked'] = ( $value || ( isset( $args['value'] ) && $value == $args['value'] ) );
|
434 |
-
break;
|
435 |
-
default:
|
436 |
-
$args['value'] = $value;
|
437 |
-
}
|
438 |
-
}
|
439 |
|
440 |
if ( !empty( $this->prefix ) ) {
|
441 |
$args['name'] = array_merge( $this->prefix, (array) $args['name'] );
|
442 |
}
|
443 |
|
444 |
-
return scbForms::
|
445 |
}
|
446 |
}
|
447 |
|
4 |
|
5 |
class scbForms {
|
6 |
|
7 |
+
const TOKEN = '%input%';
|
8 |
|
9 |
protected static $cur_name;
|
10 |
|
11 |
+
function input_with_value( $args, $value ) {
|
12 |
+
if ( !is_null( $value ) ) {
|
13 |
+
switch ( $args['type'] ) {
|
14 |
+
case 'select':
|
15 |
+
case 'radio':
|
16 |
+
$args['selected'] = $value;
|
17 |
+
break;
|
18 |
+
case 'checkbox':
|
19 |
+
if ( is_array( $value ) )
|
20 |
+
$args['checked'] = $value;
|
21 |
+
else
|
22 |
+
$args['checked'] = ( $value || ( isset( $args['value'] ) && $value == $args['value'] ) );
|
23 |
+
break;
|
24 |
+
default:
|
25 |
+
$args['value'] = $value;
|
26 |
}
|
27 |
}
|
28 |
|
29 |
+
return self::input( $args );
|
30 |
+
}
|
31 |
+
|
32 |
+
static function input( $args, $formdata = false ) {
|
33 |
+
if ( false !== $formdata ) {
|
34 |
$form = new scbForm( $formdata );
|
35 |
return $form->input( $args );
|
36 |
}
|
37 |
|
38 |
+
if ( empty( $args['name'] ) ) {
|
39 |
return trigger_error( 'Empty name', E_USER_WARNING );
|
40 |
+
}
|
41 |
|
42 |
$args = wp_parse_args( $args, array(
|
43 |
'desc' => '',
|
44 |
+
'desc_pos' => 'after',
|
45 |
+
'wrap' => self::TOKEN,
|
46 |
) );
|
47 |
|
48 |
+
if ( isset( $args['value'] ) && is_array( $args['value'] ) ) {
|
49 |
+
$args['values'] = $args['value'];
|
50 |
+
unset( $args['value'] );
|
51 |
+
}
|
52 |
|
53 |
if ( isset( $args['extra'] ) && !is_array( $args['extra'] ) )
|
54 |
$args['extra'] = shortcode_parse_atts( $args['extra'] );
|
58 |
switch ( $args['type'] ) {
|
59 |
case 'select':
|
60 |
case 'radio':
|
61 |
+
$input = self::_single_choice( $args );
|
|
|
|
|
|
|
62 |
break;
|
63 |
case 'checkbox':
|
64 |
+
if ( isset( $args['values'] ) )
|
65 |
+
$input = self::_multiple_choice( $args );
|
66 |
else
|
67 |
+
$input = self::_checkbox( $args );
|
68 |
break;
|
69 |
default:
|
70 |
+
$input = self::_input( $args );
|
71 |
}
|
72 |
+
|
73 |
+
return str_replace( self::TOKEN, $input, $args['wrap'] );
|
74 |
}
|
75 |
|
76 |
|
183 |
$checked = array();
|
184 |
|
185 |
$opts = '';
|
186 |
+
foreach ( $values as $value => $title ) {
|
187 |
if ( empty( $value ) || empty( $title ) )
|
188 |
continue;
|
189 |
|
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 );
|
200 |
}
|
201 |
|
202 |
private static function _expand_values( &$args ) {
|
203 |
+
$values =& $args['values'];
|
204 |
|
205 |
+
if ( !empty( $values ) && !self::is_associative( $values ) ) {
|
206 |
if ( is_array( $args['desc'] ) ) {
|
207 |
+
$values = array_combine( $values, $args['desc'] ); // back-compat
|
208 |
+
$args['desc'] = false;
|
209 |
+
} elseif ( !isset( $args['numeric'] ) || !$args['numeric'] ) {
|
210 |
+
$values = array_combine( $values, $values );
|
211 |
}
|
212 |
}
|
213 |
}
|
216 |
extract( $args );
|
217 |
|
218 |
if ( array( 'foo' ) == $selected ) {
|
219 |
+
// radio buttons should always have one option selected
|
220 |
+
$selected = key( $values );
|
221 |
}
|
222 |
|
223 |
$opts = '';
|
224 |
+
foreach ( $values as $value => $title ) {
|
225 |
if ( empty( $value ) || empty( $title ) )
|
226 |
continue;
|
227 |
|
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 );
|
238 |
}
|
239 |
|
240 |
private static function _select( $args ) {
|
253 |
);
|
254 |
}
|
255 |
|
256 |
+
foreach ( $values as $value => $title ) {
|
257 |
if ( empty( $value ) || empty( $title ) )
|
258 |
continue;
|
259 |
|
339 |
}
|
340 |
|
341 |
private static function add_label( $input, $desc, $desc_pos ) {
|
342 |
+
return html( 'label', self::add_desc( $input, $desc, $desc_pos ) ) . "\n";
|
343 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
344 |
|
345 |
+
private static function add_desc( $input, $desc, $desc_pos ) {
|
346 |
if ( empty( $desc ) )
|
347 |
+
return $input;
|
|
|
|
|
348 |
|
349 |
+
if ( 'before' == $desc_pos )
|
350 |
+
return $desc . ' ' . $input;
|
351 |
+
else
|
352 |
+
return $input . ' ' . $desc;
|
353 |
}
|
354 |
|
355 |
|
395 |
return $value;
|
396 |
}
|
397 |
|
398 |
+
/**
|
399 |
+
* Given a list of fields, extract the appropriate POST data and return it.
|
400 |
+
*
|
401 |
+
* @param array $fields List of args that would be sent to scbForms::input()
|
402 |
+
* @param array $to_update Existing data to update
|
403 |
+
*
|
404 |
+
* @return array
|
405 |
+
*/
|
406 |
+
static function validate_post_data( $fields, $to_update = array() ) {
|
407 |
+
foreach ( $fields as $field ) {
|
408 |
+
$value = scbForms::get_value( $field['name'], $_POST );
|
409 |
+
|
410 |
+
$value = stripslashes_deep( $value );
|
411 |
+
|
412 |
+
switch ( $field['type'] ) {
|
413 |
+
case 'checkbox':
|
414 |
+
if ( isset( $field['values'] ) && is_array( $field['values'] ) )
|
415 |
+
$value = array_intersect( $field['values'], (array) $value );
|
416 |
+
else
|
417 |
+
$value = (bool) $value;
|
418 |
+
|
419 |
+
break;
|
420 |
+
case 'radio':
|
421 |
+
case 'select':
|
422 |
+
self::_expand_values( $field );
|
423 |
+
|
424 |
+
if ( !isset( $field['values'][ $value ] ) )
|
425 |
+
continue 2;
|
426 |
+
}
|
427 |
+
|
428 |
+
self::set_value( $to_update, $field['name'], $value );
|
429 |
+
}
|
430 |
+
|
431 |
+
return $to_update;
|
432 |
+
}
|
433 |
+
|
434 |
+
static function input_from_meta( $args, $object_id, $meta_type = 'post' ) {
|
435 |
+
$single = ( 'checkbox' != $args['type'] );
|
436 |
+
|
437 |
+
$key = (array) $args['name'];
|
438 |
+
$key = end( $key );
|
439 |
+
|
440 |
+
$value = get_metadata( $meta_type, $object_id, $key, $single );
|
441 |
+
|
442 |
+
return self::input_with_value( $args, $value );
|
443 |
+
}
|
444 |
+
|
445 |
+
static function update_meta( $fields, $data, $object_id, $meta_type = 'post' ) {
|
446 |
+
foreach ( $fields as $field_args ) {
|
447 |
+
$key = $field_args['name'];
|
448 |
+
|
449 |
+
if ( 'checkbox' == $field_args['type'] ) {
|
450 |
+
$new_values = isset( $data[$key] ) ? $data[$key] : array();
|
451 |
+
|
452 |
+
$old_values = get_metadata( $meta_type, $object_id, $key );
|
453 |
+
|
454 |
+
foreach ( array_diff( $new_values, $old_values ) as $value )
|
455 |
+
add_metadata( $meta_type, $object_id, $key, $value );
|
456 |
+
|
457 |
+
foreach ( array_diff( $old_values, $new_values ) as $value )
|
458 |
+
delete_metadata( $meta_type, $object_id, $key, $value );
|
459 |
+
} else {
|
460 |
+
$value = $data[$key];
|
461 |
+
|
462 |
+
if ( '' === $value )
|
463 |
+
delete_metadata( $meta_type, $object_id, $key );
|
464 |
+
else
|
465 |
+
update_metadata( $meta_type, $object_id, $key, $value );
|
466 |
+
}
|
467 |
+
}
|
468 |
+
}
|
469 |
+
|
470 |
+
private static function set_value( &$arr, $name, $value ) {
|
471 |
+
$name = (array) $name;
|
472 |
+
|
473 |
+
$final_key = array_pop( $name );
|
474 |
+
|
475 |
+
while ( !empty( $name ) ) {
|
476 |
+
$key = array_shift( $name );
|
477 |
+
|
478 |
+
if ( !isset( $arr[ $key ] ) )
|
479 |
+
$arr[ $key ] = array();
|
480 |
+
|
481 |
+
$arr =& $arr[ $key ];
|
482 |
+
}
|
483 |
+
|
484 |
+
$arr[ $final_key ] = $value;
|
485 |
+
}
|
486 |
+
|
487 |
private static function is_associative( $array ) {
|
488 |
$keys = array_keys( $array );
|
489 |
return array_keys( $keys ) !== $keys;
|
490 |
}
|
491 |
}
|
492 |
|
493 |
+
|
494 |
/**
|
495 |
* A wrapper for scbForms, containing the formdata
|
496 |
*/
|
515 |
}
|
516 |
|
517 |
function input( $args ) {
|
518 |
+
$default = isset( $args['default'] ) ? $args['default'] : null;
|
519 |
|
520 |
+
$value = scbForms::get_value( $args['name'], $this->data, $default );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
521 |
|
522 |
if ( !empty( $this->prefix ) ) {
|
523 |
$args['name'] = array_merge( $this->prefix, (array) $args['name'] );
|
524 |
}
|
525 |
|
526 |
+
return scbForms::input_with_value( $args, $value );
|
527 |
}
|
528 |
}
|
529 |
|
scb/Options.php
CHANGED
@@ -103,7 +103,7 @@ class scbOptions {
|
|
103 |
if ( $clean )
|
104 |
$newdata = $this->_clean( $newdata );
|
105 |
|
106 |
-
update_option( $this->key, $newdata );
|
107 |
}
|
108 |
|
109 |
/**
|
@@ -126,12 +126,7 @@ class scbOptions {
|
|
126 |
|
127 |
// Keep only the keys defined in $this->defaults
|
128 |
private function _clean( $data ) {
|
129 |
-
$
|
130 |
-
foreach ( array_keys( $this->defaults ) as $key )
|
131 |
-
if ( isset( $data[$key] ) )
|
132 |
-
$r[$key] = $data[$key];
|
133 |
-
|
134 |
-
return $r;
|
135 |
}
|
136 |
|
137 |
// Get one, more or all fields from an array
|
103 |
if ( $clean )
|
104 |
$newdata = $this->_clean( $newdata );
|
105 |
|
106 |
+
update_option( $this->key, array_merge( $this->get(), $newdata ) );
|
107 |
}
|
108 |
|
109 |
/**
|
126 |
|
127 |
// Keep only the keys defined in $this->defaults
|
128 |
private function _clean( $data ) {
|
129 |
+
return wp_array_slice_assoc( $data, array_keys( $this->defaults ) );
|
|
|
|
|
|
|
|
|
|
|
130 |
}
|
131 |
|
132 |
// Get one, more or all fields from an array
|
scb/Table.php
CHANGED
@@ -8,14 +8,11 @@ class scbTable {
|
|
8 |
protected $upgrade_method;
|
9 |
|
10 |
function __construct( $name, $file, $columns, $upgrade_method = 'dbDelta' ) {
|
11 |
-
global $wpdb;
|
12 |
-
|
13 |
$this->name = $name;
|
14 |
$this->columns = $columns;
|
15 |
$this->upgrade_method = $upgrade_method;
|
16 |
|
17 |
-
|
18 |
-
$wpdb->$name = $wpdb->prefix . $name;
|
19 |
|
20 |
if ( $file ) {
|
21 |
scbUtil::add_activation_hook( $file, array( $this, 'install' ) );
|
@@ -24,36 +21,58 @@ class scbTable {
|
|
24 |
}
|
25 |
|
26 |
function install() {
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
|
29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
|
31 |
-
|
32 |
-
|
33 |
-
if ( ! empty( $wpdb->charset ) )
|
34 |
-
$charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
|
35 |
-
if ( ! empty( $wpdb->collate ) )
|
36 |
-
$charset_collate .= " COLLATE $wpdb->collate";
|
37 |
-
}
|
38 |
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
|
|
44 |
|
45 |
-
|
46 |
-
$wpdb->query( "DROP TABLE IF EXISTS $full_table_name;" );
|
47 |
|
48 |
-
|
|
|
|
|
|
|
|
|
|
|
49 |
}
|
50 |
|
51 |
-
|
52 |
-
|
|
|
|
|
|
|
53 |
|
54 |
-
|
|
|
55 |
|
56 |
-
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
58 |
}
|
59 |
|
8 |
protected $upgrade_method;
|
9 |
|
10 |
function __construct( $name, $file, $columns, $upgrade_method = 'dbDelta' ) {
|
|
|
|
|
11 |
$this->name = $name;
|
12 |
$this->columns = $columns;
|
13 |
$this->upgrade_method = $upgrade_method;
|
14 |
|
15 |
+
scb_register_table( $name );
|
|
|
16 |
|
17 |
if ( $file ) {
|
18 |
scbUtil::add_activation_hook( $file, array( $this, 'install' ) );
|
21 |
}
|
22 |
|
23 |
function install() {
|
24 |
+
scb_install_table( $this->name, $this->columns, $this->upgrade_method );
|
25 |
+
}
|
26 |
+
|
27 |
+
function uninstall() {
|
28 |
+
scb_uninstall_table( $this->name );
|
29 |
+
}
|
30 |
+
}
|
31 |
|
32 |
+
/**
|
33 |
+
* Register a table with $wpdb
|
34 |
+
*
|
35 |
+
* @param string $key The key to be used on the $wpdb object
|
36 |
+
* @param string $name The actual name of the table, without $wpdb->prefix
|
37 |
+
*/
|
38 |
+
function scb_register_table( $key, $name = false ) {
|
39 |
+
global $wpdb;
|
40 |
|
41 |
+
if ( !$name )
|
42 |
+
$name = $key;
|
|
|
|
|
|
|
|
|
|
|
43 |
|
44 |
+
$wpdb->tables[] = $name;
|
45 |
+
$wpdb->$key = $wpdb->prefix . $name;
|
46 |
+
}
|
47 |
+
|
48 |
+
function scb_install_table( $key, $columns, $upgrade_method = 'dbDelta' ) {
|
49 |
+
global $wpdb;
|
50 |
|
51 |
+
$full_table_name = $wpdb->$key;
|
|
|
52 |
|
53 |
+
$charset_collate = '';
|
54 |
+
if ( $wpdb->has_cap( 'collation' ) ) {
|
55 |
+
if ( ! empty( $wpdb->charset ) )
|
56 |
+
$charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
|
57 |
+
if ( ! empty( $wpdb->collate ) )
|
58 |
+
$charset_collate .= " COLLATE $wpdb->collate";
|
59 |
}
|
60 |
|
61 |
+
if ( 'dbDelta' == $upgrade_method ) {
|
62 |
+
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
63 |
+
dbDelta( "CREATE TABLE $full_table_name ( $columns ) $charset_collate" );
|
64 |
+
return;
|
65 |
+
}
|
66 |
|
67 |
+
if ( 'delete_first' == $upgrade_method )
|
68 |
+
$wpdb->query( "DROP TABLE IF EXISTS $full_table_name;" );
|
69 |
|
70 |
+
$wpdb->query( "CREATE TABLE IF NOT EXISTS $full_table_name ( $columns ) $charset_collate;" );
|
71 |
+
}
|
72 |
+
|
73 |
+
function scb_uninstall_table( $key ) {
|
74 |
+
global $wpdb;
|
75 |
+
|
76 |
+
$wpdb->query( "DROP TABLE IF EXISTS " . $wpdb->$key );
|
77 |
}
|
78 |
|
scb/Util.php
CHANGED
@@ -32,7 +32,7 @@ class scbUtil {
|
|
32 |
echo "</script>";
|
33 |
}
|
34 |
|
35 |
-
// Enable delayed activation
|
36 |
static function add_activation_hook( $plugin, $callback ) {
|
37 |
if ( defined( 'SCB_LOAD_MU' ) )
|
38 |
register_activation_hook( $plugin, $callback );
|
@@ -40,13 +40,27 @@ class scbUtil {
|
|
40 |
add_action( 'scb_activation_' . plugin_basename( $plugin ), $callback );
|
41 |
}
|
42 |
|
43 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
static function add_uninstall_hook( $plugin, $callback ) {
|
|
|
|
|
|
|
45 |
register_uninstall_hook( $plugin, '__return_false' ); // dummy
|
46 |
|
47 |
add_action( 'uninstall_' . plugin_basename( $plugin ), $callback );
|
48 |
}
|
49 |
|
|
|
|
|
|
|
|
|
|
|
50 |
// Get the current, full URL
|
51 |
static function get_current_url() {
|
52 |
return ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
@@ -103,6 +117,10 @@ class scbUtil {
|
|
103 |
}
|
104 |
}
|
105 |
|
|
|
|
|
|
|
|
|
106 |
|
107 |
// Transform a list of objects into an associative array
|
108 |
function scb_list_fold( $list, $key, $value ) {
|
32 |
echo "</script>";
|
33 |
}
|
34 |
|
35 |
+
// Enable delayed activation; to be used with scb_init()
|
36 |
static function add_activation_hook( $plugin, $callback ) {
|
37 |
if ( defined( 'SCB_LOAD_MU' ) )
|
38 |
register_activation_hook( $plugin, $callback );
|
40 |
add_action( 'scb_activation_' . plugin_basename( $plugin ), $callback );
|
41 |
}
|
42 |
|
43 |
+
// For debugging
|
44 |
+
static function do_activation( $plugin ) {
|
45 |
+
do_action( 'scb_activation_' . plugin_basename( $plugin ) );
|
46 |
+
}
|
47 |
+
|
48 |
+
// Allows more than one uninstall hooks.
|
49 |
+
// Also prevents an UPDATE query on each page load.
|
50 |
static function add_uninstall_hook( $plugin, $callback ) {
|
51 |
+
if ( !is_admin() )
|
52 |
+
return;
|
53 |
+
|
54 |
register_uninstall_hook( $plugin, '__return_false' ); // dummy
|
55 |
|
56 |
add_action( 'uninstall_' . plugin_basename( $plugin ), $callback );
|
57 |
}
|
58 |
|
59 |
+
// For debugging
|
60 |
+
static function do_uninstall( $plugin ) {
|
61 |
+
do_action( 'uninstall_' . plugin_basename( $plugin ) );
|
62 |
+
}
|
63 |
+
|
64 |
// Get the current, full URL
|
65 |
static function get_current_url() {
|
66 |
return ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
|
117 |
}
|
118 |
}
|
119 |
|
120 |
+
// Return a standard admin notice
|
121 |
+
function scb_admin_notice( $msg, $class = 'updated' ) {
|
122 |
+
return "<div class='$class fade'><p>$msg</p></div>\n";
|
123 |
+
}
|
124 |
|
125 |
// Transform a list of objects into an associative array
|
126 |
function scb_list_fold( $list, $key, $value ) {
|
scb/load.php
CHANGED
@@ -1,15 +1,20 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
$GLOBALS['_scb_data'] = array(
|
4 |
'scbUtil', 'scbOptions', 'scbForms', 'scbTable',
|
5 |
'scbWidget', 'scbAdminPage', 'scbBoxesPage',
|
6 |
'scbCron', 'scbHooks',
|
7 |
) );
|
8 |
|
9 |
if ( !class_exists( 'scbLoad4' ) ) :
|
|
|
|
|
|
|
|
|
|
|
10 |
class scbLoad4 {
|
11 |
|
12 |
-
private static $candidates;
|
13 |
private static $classes;
|
14 |
private static $callbacks = array();
|
15 |
|
1 |
<?php
|
2 |
|
3 |
+
$GLOBALS['_scb_data'] = array( 51, __FILE__, array(
|
4 |
'scbUtil', 'scbOptions', 'scbForms', 'scbTable',
|
5 |
'scbWidget', 'scbAdminPage', 'scbBoxesPage',
|
6 |
'scbCron', 'scbHooks',
|
7 |
) );
|
8 |
|
9 |
if ( !class_exists( 'scbLoad4' ) ) :
|
10 |
+
/**
|
11 |
+
* The main idea behind this class is to load the most recent version of the scb classes available.
|
12 |
+
*
|
13 |
+
* It waits until all plugins are loaded and then does some crazy hacks to make activation hooks work.
|
14 |
+
*/
|
15 |
class scbLoad4 {
|
16 |
|
17 |
+
private static $candidates = array();
|
18 |
private static $classes;
|
19 |
private static $callbacks = array();
|
20 |
|
screenshot-1.png
CHANGED
Binary file
|