Version Description
- allow passing entire objects to get_connected(), connect() etc.
- made get_related() work with posts-to-users connections
- made each_connected() work with simple array of posts
- introduced [p2p_connected] and [p2p_related] shortcodes
- allow 'default' parameter in 'fields' array
- more info
Download this release
Release Info
Developer | scribu |
Plugin | Posts 2 Posts |
Version | 1.3 |
Comparing to | |
See all releases |
Code changes from version 1.2 to 1.3
- admin/box.js +86 -63
- admin/box.php +27 -10
- admin/column.php +3 -1
- admin/fields.php +6 -1
- core/api.php +33 -37
- core/directed-type.php +78 -34
- core/extra.php +160 -0
- core/list.php +96 -0
- core/query.php +1 -1
- core/side.php +56 -76
- core/type-factory.php +2 -6
- core/type.php +101 -114
- core/util.php +15 -4
- core/widget.php +0 -98
- lang/posts-to-posts-ro_RO.mo +0 -0
- lang/posts-to-posts-ro_RO.po +46 -43
- lang/posts-to-posts.pot +34 -34
- posts-to-posts.php +5 -4
- readme.txt +13 -4
- scb/Forms.php +10 -4
- scb/load.php +1 -1
- screenshot-1.png +0 -0
- screenshot-2.png +0 -0
admin/box.js
CHANGED
@@ -1,49 +1,57 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
|
|
|
|
4 |
if (!jQuery('<input placeholder="1" />')[0].placeholder) {
|
5 |
-
setVal = function(){
|
6 |
var $this;
|
7 |
$this = jQuery(this);
|
8 |
if (!$this.val()) {
|
9 |
$this.val($this.attr('placeholder'));
|
10 |
$this.addClass('p2p-placeholder');
|
11 |
}
|
|
|
12 |
};
|
13 |
-
clearVal = function(){
|
14 |
var $this;
|
15 |
$this = jQuery(this);
|
16 |
if ($this.hasClass('p2p-placeholder')) {
|
17 |
$this.val('');
|
18 |
$this.removeClass('p2p-placeholder');
|
19 |
}
|
|
|
20 |
};
|
21 |
jQuery('.p2p-search input[placeholder]').each(setVal).focus(clearVal).blur(setVal);
|
22 |
}
|
23 |
-
return jQuery('.p2p-box').each(function(){
|
24 |
-
var $
|
25 |
$metabox = jQuery(this);
|
26 |
$connections = $metabox.find('.p2p-connections');
|
27 |
$spinner = jQuery('<img>', {
|
28 |
'src': P2PAdmin.spinner,
|
29 |
'class': 'p2p-spinner'
|
30 |
});
|
31 |
-
ajax_request = function(data, callback, type){
|
32 |
var handler;
|
33 |
-
type == null
|
34 |
-
|
35 |
-
|
36 |
-
data
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
|
|
|
|
|
|
|
|
42 |
try {
|
43 |
response = jQuery.parseJSON(response);
|
44 |
return callback(response);
|
45 |
} catch (e) {
|
46 |
-
return typeof console
|
47 |
}
|
48 |
};
|
49 |
return jQuery.ajax({
|
@@ -53,28 +61,34 @@
|
|
53 |
success: handler
|
54 |
});
|
55 |
};
|
56 |
-
PostsTab = (function(){
|
57 |
-
|
58 |
-
|
59 |
-
|
|
|
|
|
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',
|
|
|
|
|
67 |
}
|
68 |
-
|
|
|
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 |
-
|
|
|
73 |
var $navButton, new_page;
|
74 |
-
$navButton = jQuery(
|
75 |
new_page = this.params.paged;
|
76 |
if ($navButton.hasClass('inactive')) {
|
77 |
-
return
|
78 |
}
|
79 |
if ($navButton.hasClass('p2p-prev')) {
|
80 |
new_page--;
|
@@ -82,16 +96,20 @@
|
|
82 |
new_page++;
|
83 |
}
|
84 |
$spinner.appendTo(this.tab.find('.p2p-navigation'));
|
85 |
-
this.find_posts(new_page);
|
86 |
-
return false;
|
87 |
};
|
88 |
-
|
89 |
-
|
|
|
|
|
90 |
this.params.paged = new_page;
|
91 |
}
|
92 |
-
return ajax_request(this.params,
|
|
|
|
|
93 |
};
|
94 |
-
|
|
|
95 |
$spinner.remove();
|
96 |
this.tab.find('button, .p2p-results, .p2p-navigation, .p2p-notice').remove();
|
97 |
if (!response.rows) {
|
@@ -101,30 +119,33 @@
|
|
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'
|
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,
|
|
|
128 |
if (!confirm(P2PAdmin.deleteConfirmMessage)) {
|
129 |
return false;
|
130 |
}
|
@@ -133,37 +154,39 @@
|
|
133 |
data = {
|
134 |
subaction: 'clear_connections'
|
135 |
};
|
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 |
};
|
143 |
-
delete_connection = function(ev){
|
144 |
-
var $self, $td, data,
|
|
|
145 |
$self = jQuery(ev.target);
|
146 |
$td = $self.closest('td');
|
147 |
data = {
|
148 |
subaction: 'disconnect',
|
149 |
p2p_id: $self.data('p2p_id')
|
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 |
};
|
158 |
-
create_connection = function(ev){
|
159 |
-
var $self, $td, data,
|
|
|
160 |
$self = jQuery(ev.target);
|
161 |
$td = $self.closest('td');
|
162 |
data = {
|
163 |
subaction: 'connect',
|
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();
|
@@ -174,7 +197,7 @@
|
|
174 |
});
|
175 |
return false;
|
176 |
};
|
177 |
-
switch_to_tab = function(){
|
178 |
var $tab;
|
179 |
$tab = jQuery(this);
|
180 |
$metabox.find('.wp-tab-bar li').removeClass('wp-tab-active');
|
@@ -186,8 +209,8 @@
|
|
186 |
if ($connections.find('th.p2p-col-order').length) {
|
187 |
$connections.find('tbody').sortable({
|
188 |
handle: 'td.p2p-col-order',
|
189 |
-
helper: function(e, ui){
|
190 |
-
ui.children().each(function(){
|
191 |
var $this;
|
192 |
$this = jQuery(this);
|
193 |
return $this.width($this.width());
|
@@ -197,21 +220,21 @@
|
|
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 (
|
207 |
return false;
|
208 |
}
|
209 |
-
}).keyup(function(ev){
|
210 |
var delayed;
|
211 |
-
if (
|
212 |
clearTimeout(delayed);
|
213 |
}
|
214 |
-
return delayed = setTimeout(function(){
|
215 |
var searchStr;
|
216 |
searchStr = $searchInput.val();
|
217 |
if (searchStr === searchTab.params.s) {
|
@@ -224,14 +247,14 @@
|
|
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,
|
229 |
$button = jQuery(this);
|
230 |
if ($button.hasClass('inactive')) {
|
231 |
return false;
|
232 |
}
|
233 |
title = $createInput.val();
|
234 |
-
if (
|
235 |
$createInput.focus();
|
236 |
return false;
|
237 |
}
|
@@ -240,14 +263,14 @@
|
|
240 |
subaction: 'create_post',
|
241 |
post_title: title
|
242 |
};
|
243 |
-
ajax_request(data, function(response){
|
244 |
append_connection(response);
|
245 |
$createInput.val('');
|
246 |
return $button.removeClass('inactive');
|
247 |
});
|
248 |
return false;
|
249 |
});
|
250 |
-
return $createInput.keypress(function(ev){
|
251 |
if (13 === ev.keyCode) {
|
252 |
$createButton.click();
|
253 |
return false;
|
@@ -255,5 +278,5 @@
|
|
255 |
});
|
256 |
});
|
257 |
});
|
258 |
-
|
259 |
}).call(this);
|
1 |
+
// Generated by CoffeeScript 1.3.1
|
2 |
+
(function() {
|
3 |
+
|
4 |
+
jQuery(function() {
|
5 |
+
var clearVal, setVal;
|
6 |
if (!jQuery('<input placeholder="1" />')[0].placeholder) {
|
7 |
+
setVal = function() {
|
8 |
var $this;
|
9 |
$this = jQuery(this);
|
10 |
if (!$this.val()) {
|
11 |
$this.val($this.attr('placeholder'));
|
12 |
$this.addClass('p2p-placeholder');
|
13 |
}
|
14 |
+
return;
|
15 |
};
|
16 |
+
clearVal = function() {
|
17 |
var $this;
|
18 |
$this = jQuery(this);
|
19 |
if ($this.hasClass('p2p-placeholder')) {
|
20 |
$this.val('');
|
21 |
$this.removeClass('p2p-placeholder');
|
22 |
}
|
23 |
+
return;
|
24 |
};
|
25 |
jQuery('.p2p-search input[placeholder]').each(setVal).focus(clearVal).blur(setVal);
|
26 |
}
|
27 |
+
return jQuery('.p2p-box').each(function() {
|
28 |
+
var $connections, $createButton, $createInput, $metabox, $searchInput, $spinner, $viewAll, PostsTab, ajax_request, append_connection, clear_connections, create_connection, delete_connection, maybe_hide_table, refresh_candidates, row_ajax_request, searchTab, switch_to_tab;
|
29 |
$metabox = jQuery(this);
|
30 |
$connections = $metabox.find('.p2p-connections');
|
31 |
$spinner = jQuery('<img>', {
|
32 |
'src': P2PAdmin.spinner,
|
33 |
'class': 'p2p-spinner'
|
34 |
});
|
35 |
+
ajax_request = function(data, callback, type) {
|
36 |
var handler;
|
37 |
+
if (type == null) {
|
38 |
+
type = 'POST';
|
39 |
+
}
|
40 |
+
jQuery.extend(data, {
|
41 |
+
action: 'p2p_box',
|
42 |
+
nonce: P2PAdmin.nonce,
|
43 |
+
p2p_type: $metabox.data('p2p_type'),
|
44 |
+
direction: $metabox.data('direction'),
|
45 |
+
from: jQuery('#post_ID').val(),
|
46 |
+
s: searchTab.params.s,
|
47 |
+
paged: searchTab.params.paged
|
48 |
+
});
|
49 |
+
handler = function(response) {
|
50 |
try {
|
51 |
response = jQuery.parseJSON(response);
|
52 |
return callback(response);
|
53 |
} catch (e) {
|
54 |
+
return typeof console !== "undefined" && console !== null ? console.error('Malformed response', response) : void 0;
|
55 |
}
|
56 |
};
|
57 |
return jQuery.ajax({
|
61 |
success: handler
|
62 |
});
|
63 |
};
|
64 |
+
PostsTab = (function() {
|
65 |
+
|
66 |
+
PostsTab.name = 'PostsTab';
|
67 |
+
|
68 |
+
function PostsTab(selector) {
|
69 |
+
var _this = this;
|
70 |
this.tab = $metabox.find(selector);
|
71 |
this.params = {
|
72 |
subaction: 'search',
|
73 |
s: ''
|
74 |
};
|
75 |
this.init_pagination_data();
|
76 |
+
this.tab.delegate('.p2p-prev, .p2p-next', 'click', function(ev) {
|
77 |
+
return _this.change_page(ev.target);
|
78 |
+
});
|
79 |
}
|
80 |
+
|
81 |
+
PostsTab.prototype.init_pagination_data = function() {
|
82 |
this.params.paged = this.tab.find('.p2p-current').data('num') || 1;
|
83 |
return this.total_pages = this.tab.find('.p2p-total').data('num') || 1;
|
84 |
};
|
85 |
+
|
86 |
+
PostsTab.prototype.change_page = function(button) {
|
87 |
var $navButton, new_page;
|
88 |
+
$navButton = jQuery(button);
|
89 |
new_page = this.params.paged;
|
90 |
if ($navButton.hasClass('inactive')) {
|
91 |
+
return;
|
92 |
}
|
93 |
if ($navButton.hasClass('p2p-prev')) {
|
94 |
new_page--;
|
96 |
new_page++;
|
97 |
}
|
98 |
$spinner.appendTo(this.tab.find('.p2p-navigation'));
|
99 |
+
return this.find_posts(new_page);
|
|
|
100 |
};
|
101 |
+
|
102 |
+
PostsTab.prototype.find_posts = function(new_page) {
|
103 |
+
var _this = this;
|
104 |
+
if ((0 < new_page && new_page <= this.total_pages)) {
|
105 |
this.params.paged = new_page;
|
106 |
}
|
107 |
+
return ajax_request(this.params, function(response) {
|
108 |
+
return _this.update_rows(response);
|
109 |
+
}, 'GET');
|
110 |
};
|
111 |
+
|
112 |
+
PostsTab.prototype.update_rows = function(response) {
|
113 |
$spinner.remove();
|
114 |
this.tab.find('button, .p2p-results, .p2p-navigation, .p2p-notice').remove();
|
115 |
if (!response.rows) {
|
119 |
return this.init_pagination_data();
|
120 |
}
|
121 |
};
|
122 |
+
|
123 |
return PostsTab;
|
124 |
+
|
125 |
+
})();
|
126 |
searchTab = new PostsTab('.p2p-tab-search');
|
127 |
+
row_ajax_request = function($td, data, callback) {
|
128 |
$td.html($spinner.show());
|
129 |
return ajax_request(data, callback);
|
130 |
};
|
131 |
+
maybe_hide_table = function($table) {
|
132 |
if (!$table.find('tbody tr').length) {
|
133 |
return $table.hide();
|
134 |
}
|
135 |
};
|
136 |
+
append_connection = function(response) {
|
137 |
$connections.show().find('tbody').append(response.row);
|
138 |
+
if ('one' === $metabox.data('cardinality')) {
|
139 |
return $metabox.find('.p2p-create-connections').hide();
|
140 |
}
|
141 |
};
|
142 |
+
refresh_candidates = function(results) {
|
143 |
$metabox.find('.p2p-create-connections').show();
|
144 |
return searchTab.update_rows(results);
|
145 |
};
|
146 |
+
clear_connections = function(ev) {
|
147 |
+
var $self, $td, data,
|
148 |
+
_this = this;
|
149 |
if (!confirm(P2PAdmin.deleteConfirmMessage)) {
|
150 |
return false;
|
151 |
}
|
154 |
data = {
|
155 |
subaction: 'clear_connections'
|
156 |
};
|
157 |
+
row_ajax_request($td, data, function(response) {
|
158 |
$connections.hide().find('tbody').html('');
|
159 |
$td.html($self);
|
160 |
return refresh_candidates(response);
|
161 |
});
|
162 |
return false;
|
163 |
};
|
164 |
+
delete_connection = function(ev) {
|
165 |
+
var $self, $td, data,
|
166 |
+
_this = this;
|
167 |
$self = jQuery(ev.target);
|
168 |
$td = $self.closest('td');
|
169 |
data = {
|
170 |
subaction: 'disconnect',
|
171 |
p2p_id: $self.data('p2p_id')
|
172 |
};
|
173 |
+
row_ajax_request($td, data, function(response) {
|
174 |
$td.closest('tr').remove();
|
175 |
maybe_hide_table($connections);
|
176 |
return refresh_candidates(response);
|
177 |
});
|
178 |
return false;
|
179 |
};
|
180 |
+
create_connection = function(ev) {
|
181 |
+
var $self, $td, data,
|
182 |
+
_this = this;
|
183 |
$self = jQuery(ev.target);
|
184 |
$td = $self.closest('td');
|
185 |
data = {
|
186 |
subaction: 'connect',
|
187 |
to: $self.data('post_id')
|
188 |
};
|
189 |
+
row_ajax_request($td, data, function(response) {
|
190 |
append_connection(response);
|
191 |
if ($metabox.data('prevent_duplicates')) {
|
192 |
$td.closest('tr').remove();
|
197 |
});
|
198 |
return false;
|
199 |
};
|
200 |
+
switch_to_tab = function() {
|
201 |
var $tab;
|
202 |
$tab = jQuery(this);
|
203 |
$metabox.find('.wp-tab-bar li').removeClass('wp-tab-active');
|
209 |
if ($connections.find('th.p2p-col-order').length) {
|
210 |
$connections.find('tbody').sortable({
|
211 |
handle: 'td.p2p-col-order',
|
212 |
+
helper: function(e, ui) {
|
213 |
+
ui.children().each(function() {
|
214 |
var $this;
|
215 |
$this = jQuery(this);
|
216 |
return $this.width($this.width());
|
220 |
});
|
221 |
}
|
222 |
$viewAll = $metabox.find('.p2p-tab-search button');
|
223 |
+
$viewAll.click(function() {
|
224 |
searchTab.find_posts(1);
|
225 |
return false;
|
226 |
});
|
227 |
$searchInput = $metabox.find('.p2p-tab-search :text');
|
228 |
+
$searchInput.keypress(function(ev) {
|
229 |
+
if (ev.keyCode === 13) {
|
230 |
return false;
|
231 |
}
|
232 |
+
}).keyup(function(ev) {
|
233 |
var delayed;
|
234 |
+
if (delayed !== void 0) {
|
235 |
clearTimeout(delayed);
|
236 |
}
|
237 |
+
return delayed = setTimeout(function() {
|
238 |
var searchStr;
|
239 |
searchStr = $searchInput.val();
|
240 |
if (searchStr === searchTab.params.s) {
|
247 |
});
|
248 |
$createButton = $metabox.find('.p2p-tab-create-post button');
|
249 |
$createInput = $metabox.find('.p2p-tab-create-post :text');
|
250 |
+
$createButton.click(function() {
|
251 |
+
var $button, data, title;
|
252 |
$button = jQuery(this);
|
253 |
if ($button.hasClass('inactive')) {
|
254 |
return false;
|
255 |
}
|
256 |
title = $createInput.val();
|
257 |
+
if (title === '') {
|
258 |
$createInput.focus();
|
259 |
return false;
|
260 |
}
|
263 |
subaction: 'create_post',
|
264 |
post_title: title
|
265 |
};
|
266 |
+
ajax_request(data, function(response) {
|
267 |
append_connection(response);
|
268 |
$createInput.val('');
|
269 |
return $button.removeClass('inactive');
|
270 |
});
|
271 |
return false;
|
272 |
});
|
273 |
+
return $createInput.keypress(function(ev) {
|
274 |
if (13 === ev.keyCode) {
|
275 |
$createButton.click();
|
276 |
return false;
|
278 |
});
|
279 |
});
|
280 |
});
|
281 |
+
|
282 |
}).call(this);
|
admin/box.php
CHANGED
@@ -14,6 +14,12 @@ class P2P_Box {
|
|
14 |
|
15 |
private $columns;
|
16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
function __construct( $args, $ctype ) {
|
18 |
$this->args = $args;
|
19 |
|
@@ -70,12 +76,15 @@ class P2P_Box {
|
|
70 |
echo P2P_Mustache::render( 'box', $data );
|
71 |
}
|
72 |
|
73 |
-
protected function get_folded_connections( $
|
74 |
-
$
|
|
|
|
|
|
|
75 |
|
76 |
-
$query = $this->ctype->get_connected( $
|
77 |
|
78 |
-
return scb_list_fold( $
|
79 |
}
|
80 |
|
81 |
protected function render_data_attributes() {
|
@@ -175,7 +184,13 @@ class P2P_Box {
|
|
175 |
}
|
176 |
|
177 |
protected function post_rows( $current_post_id, $page = 1, $search = '' ) {
|
178 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
|
180 |
if ( empty( $candidate->items ) )
|
181 |
return false;
|
@@ -242,10 +257,10 @@ class P2P_Box {
|
|
242 |
|
243 |
$p2p_id = $this->ctype->connect( $from, $to );
|
244 |
|
245 |
-
if ( $p2p_id )
|
246 |
-
$r = array( '
|
247 |
else
|
248 |
-
$r = array( '
|
249 |
|
250 |
die( json_encode( $r ) );
|
251 |
}
|
@@ -257,7 +272,7 @@ class P2P_Box {
|
|
257 |
}
|
258 |
|
259 |
public function ajax_clear_connections() {
|
260 |
-
$this->ctype->
|
261 |
|
262 |
$this->refresh_candidates();
|
263 |
}
|
@@ -305,7 +320,9 @@ class P2P_Box {
|
|
305 |
}
|
306 |
|
307 |
public function check_capability() {
|
308 |
-
|
|
|
|
|
309 |
}
|
310 |
}
|
311 |
|
14 |
|
15 |
private $columns;
|
16 |
|
17 |
+
private static $admin_box_qv = array(
|
18 |
+
'update_post_term_cache' => false,
|
19 |
+
'update_post_meta_cache' => false,
|
20 |
+
'post_status' => 'any',
|
21 |
+
);
|
22 |
+
|
23 |
function __construct( $args, $ctype ) {
|
24 |
$this->args = $args;
|
25 |
|
76 |
echo P2P_Mustache::render( 'box', $data );
|
77 |
}
|
78 |
|
79 |
+
protected function get_folded_connections( $post ) {
|
80 |
+
$extra_qv = array_merge( self::$admin_box_qv, array(
|
81 |
+
'p2p:context' => 'admin_box',
|
82 |
+
'p2p:per_page' => -1
|
83 |
+
) );
|
84 |
|
85 |
+
$query = $this->ctype->get_connected( $post, $extra_qv, 'abstract' );
|
86 |
|
87 |
+
return scb_list_fold( $query->items, 'p2p_id', 'ID' );
|
88 |
}
|
89 |
|
90 |
protected function render_data_attributes() {
|
184 |
}
|
185 |
|
186 |
protected function post_rows( $current_post_id, $page = 1, $search = '' ) {
|
187 |
+
$extra_qv = array_merge( self::$admin_box_qv, array(
|
188 |
+
'p2p:search' => $search,
|
189 |
+
'p2p:page' => $page,
|
190 |
+
'p2p:per_page' => 5
|
191 |
+
) );
|
192 |
+
|
193 |
+
$candidate = $this->ctype->get_connectable( $current_post_id, $extra_qv );
|
194 |
|
195 |
if ( empty( $candidate->items ) )
|
196 |
return false;
|
257 |
|
258 |
$p2p_id = $this->ctype->connect( $from, $to );
|
259 |
|
260 |
+
if ( is_wp_error( $p2p_id ) )
|
261 |
+
$r = array( 'error' => sprintf( __( "Can't create connection: %s", P2P_TEXTDOMAIN ), $p2p_id->get_error_message() ) );
|
262 |
else
|
263 |
+
$r = array( 'row' => $this->connection_row( $p2p_id, $to, true ) );
|
264 |
|
265 |
die( json_encode( $r ) );
|
266 |
}
|
272 |
}
|
273 |
|
274 |
public function ajax_clear_connections() {
|
275 |
+
$this->ctype->disconnect( $_POST['from'], 'any' );
|
276 |
|
277 |
$this->refresh_candidates();
|
278 |
}
|
320 |
}
|
321 |
|
322 |
public function check_capability() {
|
323 |
+
$show = $this->ctype->get_opposite( 'side' )->check_capability();
|
324 |
+
|
325 |
+
return apply_filters( 'p2p_admin_box_show', $show, $GLOBALS['post'], $this->ctype );
|
326 |
}
|
327 |
}
|
328 |
|
admin/column.php
CHANGED
@@ -9,7 +9,9 @@ class P2P_Column {
|
|
9 |
function __construct( $directed ) {
|
10 |
$this->ctype = $directed;
|
11 |
|
12 |
-
$
|
|
|
|
|
13 |
|
14 |
$this->connected = scb_list_fold( $GLOBALS['wp_query']->posts, 'ID', 'connected' );
|
15 |
}
|
9 |
function __construct( $directed ) {
|
10 |
$this->ctype = $directed;
|
11 |
|
12 |
+
$extra_qv = array( 'p2p:context' => 'admin_column' );
|
13 |
+
|
14 |
+
$this->ctype->lose_direction()->each_connected( $GLOBALS['wp_query'], $extra_qv );
|
15 |
|
16 |
$this->connected = scb_list_fold( $GLOBALS['wp_query']->posts, 'ID', 'connected' );
|
17 |
}
|
admin/fields.php
CHANGED
@@ -83,8 +83,13 @@ class P2P_Field_Generic implements P2P_Field {
|
|
83 |
if ( isset( $this->data['values'] ) )
|
84 |
$args['value'] = $this->data['values'];
|
85 |
|
86 |
-
if (
|
|
|
|
|
|
|
|
|
87 |
$args['text'] = '';
|
|
|
88 |
|
89 |
return scbForms::input_from_meta( $args, $p2p_id, 'p2p' );
|
90 |
}
|
83 |
if ( isset( $this->data['values'] ) )
|
84 |
$args['value'] = $this->data['values'];
|
85 |
|
86 |
+
if ( isset( $this->data['default'] ) ) {
|
87 |
+
$args['default'] = $this->data['default'];
|
88 |
+
if ( 'checkbox' == $args['type'] )
|
89 |
+
$args['default'] = (array) $args['default'];
|
90 |
+
} elseif ( 'select' == $args['type'] ) {
|
91 |
$args['text'] = '';
|
92 |
+
}
|
93 |
|
94 |
return scbForms::input_from_meta( $args, $p2p_id, 'p2p' );
|
95 |
}
|
core/api.php
CHANGED
@@ -304,52 +304,48 @@ function p2p_delete_meta( $p2p_id, $key, $value = '' ) {
|
|
304 |
}
|
305 |
|
306 |
/**
|
307 |
-
* List some
|
308 |
*
|
309 |
-
* @param object|array A WP_Query instance, or a list of post objects
|
310 |
* @param array $args (optional)
|
311 |
*/
|
312 |
function p2p_list_posts( $posts, $args = array() ) {
|
313 |
-
if (
|
314 |
-
$
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
'before_item' => '<li>', 'after_item' => '</li>',
|
319 |
-
'separator' => false,
|
320 |
-
'template' => false
|
321 |
-
) );
|
322 |
-
|
323 |
-
extract( $args, EXTR_SKIP );
|
324 |
-
|
325 |
-
if ( empty( $posts ) )
|
326 |
-
return;
|
327 |
-
|
328 |
-
echo $before_list;
|
329 |
-
|
330 |
-
$i = 0;
|
331 |
-
|
332 |
-
foreach ( $posts as $post ) {
|
333 |
-
$GLOBALS['post'] = $post;
|
334 |
-
|
335 |
-
setup_postdata( $post );
|
336 |
-
|
337 |
-
if ( !$separator ) echo $before_item;
|
338 |
-
|
339 |
-
if ( $template )
|
340 |
-
locate_template( $template, true, false );
|
341 |
-
else
|
342 |
-
if ( 0 < $i && $separator ) echo $separator;
|
343 |
|
344 |
-
|
|
|
345 |
|
346 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
347 |
|
348 |
-
|
|
|
|
|
349 |
}
|
350 |
|
351 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
352 |
|
353 |
-
|
|
|
354 |
}
|
355 |
|
304 |
}
|
305 |
|
306 |
/**
|
307 |
+
* List some items.
|
308 |
*
|
309 |
+
* @param object|array A P2P_List instance, a WP_Query instance, or a list of post objects
|
310 |
* @param array $args (optional)
|
311 |
*/
|
312 |
function p2p_list_posts( $posts, $args = array() ) {
|
313 |
+
if ( is_a( $posts, 'P2P_List' ) ) {
|
314 |
+
$list = $posts;
|
315 |
+
} else {
|
316 |
+
$list = new P2P_List_Post( $posts );
|
317 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
318 |
|
319 |
+
return $list->render( $args );
|
320 |
+
}
|
321 |
|
322 |
+
/**
|
323 |
+
* Given a list of objects and another list of connected items,
|
324 |
+
* distribute each connected item to it's respective counterpart.
|
325 |
+
*
|
326 |
+
* @param array List of objects
|
327 |
+
* @param array List of connected objects
|
328 |
+
* @param string Name of connected array property
|
329 |
+
*/
|
330 |
+
function p2p_distribute_connected( $items, $connected, $prop_name ) {
|
331 |
+
$indexed_list = array();
|
332 |
|
333 |
+
foreach ( $items as $item ) {
|
334 |
+
$item->$prop_name = array();
|
335 |
+
$indexed_list[ $item->ID ] = $item;
|
336 |
}
|
337 |
|
338 |
+
foreach ( $connected as $inner_item ) {
|
339 |
+
if ( $inner_item->ID == $inner_item->p2p_from ) {
|
340 |
+
$outer_item_id = $inner_item->p2p_to;
|
341 |
+
} elseif ( $inner_item->ID == $inner_item->p2p_to ) {
|
342 |
+
$outer_item_id = $inner_item->p2p_from;
|
343 |
+
} else {
|
344 |
+
trigger_error( "Corrupted data for item $inner_item->ID", E_USER_WARNING );
|
345 |
+
continue;
|
346 |
+
}
|
347 |
|
348 |
+
array_push( $indexed_list[ $outer_item_id ]->$prop_name, $inner_item );
|
349 |
+
}
|
350 |
}
|
351 |
|
core/directed-type.php
CHANGED
@@ -30,6 +30,15 @@ class P2P_Directed_Connection_Type {
|
|
30 |
return $this->ctype;
|
31 |
}
|
32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
public function get_opposite( $key ) {
|
34 |
$direction = ( 'to' == $this->direction ) ? 'from' : 'to';
|
35 |
|
@@ -48,30 +57,58 @@ class P2P_Directed_Connection_Type {
|
|
48 |
return $arg[$direction];
|
49 |
}
|
50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
/**
|
52 |
-
* Get a list of posts
|
53 |
*
|
54 |
-
* @param
|
55 |
* @param array $extra_qv Additional query variables to use.
|
56 |
*
|
57 |
-
* @return object
|
58 |
*/
|
59 |
-
public function
|
60 |
-
$
|
61 |
-
'connected_items' => $post_id
|
62 |
-
) );
|
63 |
|
64 |
-
$
|
65 |
|
66 |
-
$
|
67 |
|
68 |
-
|
69 |
-
|
70 |
|
71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
}
|
73 |
|
74 |
public function get_connected_args( $q ) {
|
|
|
|
|
|
|
|
|
75 |
if ( $orderby_key = $this->get_orderby_key() ) {
|
76 |
$q = wp_parse_args( $q, array(
|
77 |
'connected_orderby' => $orderby_key,
|
@@ -80,7 +117,7 @@ class P2P_Directed_Connection_Type {
|
|
80 |
) );
|
81 |
}
|
82 |
|
83 |
-
$q = array_merge( $this->get_opposite( 'side' )->get_base_qv(
|
84 |
'p2p_type' => array( $this->name => $this->get_direction() ),
|
85 |
) );
|
86 |
|
@@ -106,18 +143,20 @@ class P2P_Directed_Connection_Type {
|
|
106 |
}
|
107 |
|
108 |
/**
|
109 |
-
* Get a list of
|
110 |
*
|
111 |
* @param int $post_id A post id.
|
112 |
*/
|
113 |
-
public function get_connectable( $item_id, $
|
114 |
$side = $this->get_opposite( 'side' );
|
115 |
|
116 |
-
$
|
117 |
|
118 |
-
$
|
119 |
|
120 |
-
|
|
|
|
|
121 |
}
|
122 |
|
123 |
private function get_non_connectable( $item_id ) {
|
@@ -145,17 +184,19 @@ class P2P_Directed_Connection_Type {
|
|
145 |
/**
|
146 |
* Connect two items.
|
147 |
*
|
148 |
-
* @param
|
149 |
-
* @param
|
150 |
* @param array Additional information about the connection.
|
151 |
*
|
152 |
* @return int|object p2p_id or WP_Error on failure
|
153 |
*/
|
154 |
public function connect( $from, $to, $meta = array() ) {
|
155 |
-
|
|
|
156 |
return new WP_Error( 'first_parameter', 'Invalid first parameter.' );
|
157 |
|
158 |
-
|
|
|
159 |
return new WP_Error( 'second_parameter', 'Invalid second parameter.' );
|
160 |
|
161 |
if ( !$this->self_connections && $from == $to )
|
@@ -178,22 +219,25 @@ class P2P_Directed_Connection_Type {
|
|
178 |
}
|
179 |
|
180 |
/**
|
181 |
-
* Disconnect two
|
|
|
|
|
|
|
182 |
*
|
183 |
-
* @
|
184 |
-
* @param int The second end of the connection.
|
185 |
*/
|
186 |
public function disconnect( $from, $to ) {
|
187 |
-
|
188 |
-
|
|
|
189 |
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
return $this->delete_connections( compact( 'from' ) );
|
197 |
}
|
198 |
|
199 |
public function get_p2p_id( $from, $to ) {
|
30 |
return $this->ctype;
|
31 |
}
|
32 |
|
33 |
+
public function flip_direction() {
|
34 |
+
if ( 'any' == $this->direction )
|
35 |
+
return $this;
|
36 |
+
|
37 |
+
$direction = ( 'to' == $this->direction ) ? 'from' : 'to';
|
38 |
+
|
39 |
+
return $this->set_direction( $direction );
|
40 |
+
}
|
41 |
+
|
42 |
public function get_opposite( $key ) {
|
43 |
$direction = ( 'to' == $this->direction ) ? 'from' : 'to';
|
44 |
|
57 |
return $arg[$direction];
|
58 |
}
|
59 |
|
60 |
+
private function abstract_query( $qv, $side, $output = 'abstract' ) {
|
61 |
+
$query = $side->do_query( $qv );
|
62 |
+
|
63 |
+
if ( 'raw' == $output )
|
64 |
+
return $query;
|
65 |
+
|
66 |
+
$class = str_replace( 'P2P_Side_', 'P2P_List_', get_class( $side ) );
|
67 |
+
|
68 |
+
return new $class( $query );
|
69 |
+
}
|
70 |
+
|
71 |
/**
|
72 |
+
* Get a list of posts connected to other posts connected to a post.
|
73 |
*
|
74 |
+
* @param mixed $item An object, an object id or an array of such.
|
75 |
* @param array $extra_qv Additional query variables to use.
|
76 |
*
|
77 |
+
* @return bool|object False on failure; A WP_Query instance on success.
|
78 |
*/
|
79 |
+
public function get_related( $item, $extra_qv = array(), $output = 'raw' ) {
|
80 |
+
$extra_qv['fields'] = 'ids';
|
|
|
|
|
81 |
|
82 |
+
$connected = $this->get_connected( $item, $extra_qv, 'abstract' );
|
83 |
|
84 |
+
$additional_qv = array( 'p2p:exclude' => _p2p_normalize( $item ) );
|
85 |
|
86 |
+
return $this->flip_direction()->get_connected( $connected->items, $additional_qv, $output );
|
87 |
+
}
|
88 |
|
89 |
+
/**
|
90 |
+
* Get a list of items that are connected to a given item.
|
91 |
+
*
|
92 |
+
* @param mixed $item An object, an object id or an array of such.
|
93 |
+
* @param array $extra_qv Additional query variables to use.
|
94 |
+
*
|
95 |
+
* @return object
|
96 |
+
*/
|
97 |
+
public function get_connected( $item, $extra_qv = array(), $output = 'raw' ) {
|
98 |
+
$side = $this->get_opposite( 'side' );
|
99 |
+
|
100 |
+
$args = array_merge( $side->translate_qv( $extra_qv ), array(
|
101 |
+
'connected_items' => $item
|
102 |
+
) );
|
103 |
+
|
104 |
+
return $this->abstract_query( $this->get_connected_args( $args ), $side, $output );
|
105 |
}
|
106 |
|
107 |
public function get_connected_args( $q ) {
|
108 |
+
$q = wp_parse_args( $q, array(
|
109 |
+
'p2p:context' => false
|
110 |
+
) );
|
111 |
+
|
112 |
if ( $orderby_key = $this->get_orderby_key() ) {
|
113 |
$q = wp_parse_args( $q, array(
|
114 |
'connected_orderby' => $orderby_key,
|
117 |
) );
|
118 |
}
|
119 |
|
120 |
+
$q = array_merge( $this->get_opposite( 'side' )->get_base_qv( $q ), array(
|
121 |
'p2p_type' => array( $this->name => $this->get_direction() ),
|
122 |
) );
|
123 |
|
143 |
}
|
144 |
|
145 |
/**
|
146 |
+
* Get a list of items that could be connected to a given item.
|
147 |
*
|
148 |
* @param int $post_id A post id.
|
149 |
*/
|
150 |
+
public function get_connectable( $item_id, $extra_qv = array() ) {
|
151 |
$side = $this->get_opposite( 'side' );
|
152 |
|
153 |
+
$extra_qv['p2p:exclude'] = $this->get_non_connectable( $item_id );
|
154 |
|
155 |
+
$extra_qv = $side->get_base_qv( $side->translate_qv( $extra_qv ) );
|
156 |
|
157 |
+
$qv = apply_filters( 'p2p_connectable_args', $extra_qv, $this, $item_id );
|
158 |
+
|
159 |
+
return $this->abstract_query( $qv, $side );
|
160 |
}
|
161 |
|
162 |
private function get_non_connectable( $item_id ) {
|
184 |
/**
|
185 |
* Connect two items.
|
186 |
*
|
187 |
+
* @param mixed The first end of the connection.
|
188 |
+
* @param mixed The second end of the connection.
|
189 |
* @param array Additional information about the connection.
|
190 |
*
|
191 |
* @return int|object p2p_id or WP_Error on failure
|
192 |
*/
|
193 |
public function connect( $from, $to, $meta = array() ) {
|
194 |
+
$from = $this->get_current( 'side' )->item_id( $from );
|
195 |
+
if ( !$from )
|
196 |
return new WP_Error( 'first_parameter', 'Invalid first parameter.' );
|
197 |
|
198 |
+
$to = $this->get_opposite( 'side' )->item_id( $to );
|
199 |
+
if ( !$to )
|
200 |
return new WP_Error( 'second_parameter', 'Invalid second parameter.' );
|
201 |
|
202 |
if ( !$this->self_connections && $from == $to )
|
219 |
}
|
220 |
|
221 |
/**
|
222 |
+
* Disconnect two items.
|
223 |
+
*
|
224 |
+
* @param mixed The first end of the connection.
|
225 |
+
* @param mixed The second end of the connection or 'any'.
|
226 |
*
|
227 |
+
* @return int|object count or WP_Error on failure
|
|
|
228 |
*/
|
229 |
public function disconnect( $from, $to ) {
|
230 |
+
$from = $this->get_current( 'side' )->item_id( $from );
|
231 |
+
if ( !$from )
|
232 |
+
return new WP_Error( 'first_parameter', 'Invalid first parameter.' );
|
233 |
|
234 |
+
if ( 'any' != $to ) {
|
235 |
+
$to = $this->get_opposite( 'side' )->item_id( $to );
|
236 |
+
if ( !$to )
|
237 |
+
return new WP_Error( 'second_parameter', 'Invalid second parameter.' );
|
238 |
+
}
|
239 |
+
|
240 |
+
return $this->delete_connections( compact( 'from', 'to' ) );
|
241 |
}
|
242 |
|
243 |
public function get_p2p_id( $from, $to ) {
|
core/extra.php
ADDED
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class P2P_Widget extends scbWidget {
|
4 |
+
|
5 |
+
protected $defaults = array(
|
6 |
+
'ctype' => false,
|
7 |
+
'listing' => 'connected',
|
8 |
+
'title' => ''
|
9 |
+
);
|
10 |
+
|
11 |
+
static function init() {
|
12 |
+
parent::init( __CLASS__, false, 'p2p' );
|
13 |
+
}
|
14 |
+
|
15 |
+
function __construct() {
|
16 |
+
parent::__construct( 'p2p', __( 'Posts 2 Posts', P2P_TEXTDOMAIN ), array(
|
17 |
+
'description' => __( 'A list of posts connected to the current post', P2P_TEXTDOMAIN )
|
18 |
+
) );
|
19 |
+
}
|
20 |
+
|
21 |
+
function form( $instance ) {
|
22 |
+
if ( empty( $instance ) )
|
23 |
+
$instance = $this->defaults;
|
24 |
+
|
25 |
+
$ctypes = array();
|
26 |
+
|
27 |
+
foreach ( P2P_Connection_Type_Factory::get_all_instances() as $p2p_type => $ctype ) {
|
28 |
+
if ( ! $ctype instanceof P2P_Connection_Type )
|
29 |
+
continue;
|
30 |
+
|
31 |
+
$ctypes[ $p2p_type ] = $ctype->get_desc();
|
32 |
+
}
|
33 |
+
|
34 |
+
echo html( 'p', $this->input( array(
|
35 |
+
'type' => 'text',
|
36 |
+
'name' => 'title',
|
37 |
+
'desc' => __( 'Title:', P2P_TEXTDOMAIN )
|
38 |
+
), $instance ) );
|
39 |
+
|
40 |
+
echo html( 'p', $this->input( array(
|
41 |
+
'type' => 'select',
|
42 |
+
'name' => 'ctype',
|
43 |
+
'values' => $ctypes,
|
44 |
+
'desc' => __( 'Connection type:', P2P_TEXTDOMAIN )
|
45 |
+
), $instance ) );
|
46 |
+
|
47 |
+
echo html( 'p',
|
48 |
+
__( 'Connection listing:', P2P_TEXTDOMAIN ),
|
49 |
+
'<br>',
|
50 |
+
$this->input( array(
|
51 |
+
'type' => 'radio',
|
52 |
+
'name' => 'listing',
|
53 |
+
'values' => array(
|
54 |
+
'connected' => __( 'connected', P2P_TEXTDOMAIN ),
|
55 |
+
'related' => __( 'related', P2P_TEXTDOMAIN )
|
56 |
+
),
|
57 |
+
), $instance )
|
58 |
+
);
|
59 |
+
}
|
60 |
+
|
61 |
+
function widget( $args, $instance ) {
|
62 |
+
$instance = array_merge( $this->defaults, $instance );
|
63 |
+
|
64 |
+
$output = _p2p_get_list( array(
|
65 |
+
'ctype' => $instance['ctype'],
|
66 |
+
'method' => ( 'related' == $instance['listing'] ? 'get_related' : 'get_connected' ),
|
67 |
+
'item' => get_queried_object(),
|
68 |
+
'mode' => 'ul',
|
69 |
+
'context' => 'widget'
|
70 |
+
) );
|
71 |
+
|
72 |
+
if ( !$output )
|
73 |
+
return;
|
74 |
+
|
75 |
+
$title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
|
76 |
+
|
77 |
+
extract( $args );
|
78 |
+
|
79 |
+
echo $before_widget;
|
80 |
+
|
81 |
+
if ( ! empty( $title ) )
|
82 |
+
echo $before_title . $title . $after_title;
|
83 |
+
|
84 |
+
echo $output;
|
85 |
+
|
86 |
+
echo $after_widget;
|
87 |
+
}
|
88 |
+
}
|
89 |
+
|
90 |
+
|
91 |
+
class P2P_Shortcodes {
|
92 |
+
|
93 |
+
static function init() {
|
94 |
+
add_shortcode( 'p2p_connected', array( __CLASS__, 'connected' ) );
|
95 |
+
add_shortcode( 'p2p_related', array( __CLASS__, 'related' ) );
|
96 |
+
}
|
97 |
+
|
98 |
+
static function connected( $attr ) {
|
99 |
+
return self::get_list( $attr, 'get_connected' );
|
100 |
+
}
|
101 |
+
|
102 |
+
static function related( $attr ) {
|
103 |
+
return self::get_list( $attr, 'get_related' );
|
104 |
+
}
|
105 |
+
|
106 |
+
private static function get_list( $attr, $method ) {
|
107 |
+
global $post;
|
108 |
+
|
109 |
+
$attr = shortcode_atts( array(
|
110 |
+
'type' => '',
|
111 |
+
'mode' => 'ul',
|
112 |
+
), $attr );
|
113 |
+
|
114 |
+
return _p2p_get_list( array(
|
115 |
+
'ctype' => $attr['type'],
|
116 |
+
'method' => $method,
|
117 |
+
'item' => $post,
|
118 |
+
'mode' => $attr['mode'],
|
119 |
+
'context' => 'shortcode'
|
120 |
+
) );
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
124 |
+
|
125 |
+
/** @internal */
|
126 |
+
function _p2p_get_list( $args ) {
|
127 |
+
extract( $args );
|
128 |
+
|
129 |
+
$ctype = p2p_type( $ctype );
|
130 |
+
if ( !$ctype ) {
|
131 |
+
trigger_error( sprintf( "Unregistered connection type '%s'.", $ctype ), E_USER_WARNING );
|
132 |
+
return '';
|
133 |
+
}
|
134 |
+
|
135 |
+
$directed = $ctype->find_direction( $item );
|
136 |
+
if ( !$directed )
|
137 |
+
return '';
|
138 |
+
|
139 |
+
$extra_qv = array(
|
140 |
+
'p2p:per_page' => -1,
|
141 |
+
'p2p:context' => $context
|
142 |
+
);
|
143 |
+
|
144 |
+
$connected = $directed->$method( $item, $extra_qv, 'abstract' );
|
145 |
+
|
146 |
+
$args = array(
|
147 |
+
'before_list' => '<ul id="' . $ctype->name . '_list">',
|
148 |
+
'echo' => false
|
149 |
+
);
|
150 |
+
|
151 |
+
if ( 'ol' == $mode ) {
|
152 |
+
_p2p_append( $args, array(
|
153 |
+
'before_list' => '<ol id="' . $ctype->name . '_list">',
|
154 |
+
'after_list' => '</ol>',
|
155 |
+
) );
|
156 |
+
}
|
157 |
+
|
158 |
+
return apply_filters( "p2p_{$context}_html", $connected->render( $args ), $connected, $directed, $mode );
|
159 |
+
}
|
160 |
+
|
core/list.php
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
abstract class P2P_List {
|
4 |
+
|
5 |
+
public $items;
|
6 |
+
public $current_page = 1;
|
7 |
+
public $total_pages = 0;
|
8 |
+
|
9 |
+
function render( $args = array() ) {
|
10 |
+
if ( empty( $this->items ) )
|
11 |
+
return '';
|
12 |
+
|
13 |
+
$args = wp_parse_args( $args, array(
|
14 |
+
'before_list' => '<ul>', 'after_list' => '</ul>',
|
15 |
+
'before_item' => '<li>', 'after_item' => '</li>',
|
16 |
+
'separator' => false,
|
17 |
+
'echo' => true
|
18 |
+
) );
|
19 |
+
|
20 |
+
extract( $args, EXTR_SKIP );
|
21 |
+
|
22 |
+
if ( $separator ) {
|
23 |
+
if ( '<ul>' == $before_list )
|
24 |
+
$before_list = '';
|
25 |
+
|
26 |
+
if ( '</ul>' == $after_list )
|
27 |
+
$after_list = '';
|
28 |
+
}
|
29 |
+
|
30 |
+
if ( !$echo )
|
31 |
+
ob_start();
|
32 |
+
|
33 |
+
echo $before_list;
|
34 |
+
|
35 |
+
if ( $separator ) {
|
36 |
+
echo implode( $separator, array_map( array( $this, 'render_item' ), $this->items ) );
|
37 |
+
} else {
|
38 |
+
foreach ( $this->items as $item ) {
|
39 |
+
echo $before_item . $this->render_item( $item ) . $after_item;
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
echo $after_list;
|
44 |
+
|
45 |
+
if ( !$echo )
|
46 |
+
return ob_get_clean();
|
47 |
+
}
|
48 |
+
|
49 |
+
abstract protected function render_item( $item );
|
50 |
+
}
|
51 |
+
|
52 |
+
|
53 |
+
class P2P_List_Post extends P2P_List {
|
54 |
+
|
55 |
+
function __construct( $wp_query ) {
|
56 |
+
if ( is_array( $wp_query ) ) {
|
57 |
+
$this->items = $wp_query;
|
58 |
+
} else {
|
59 |
+
$this->items = $wp_query->posts;
|
60 |
+
$this->current_page = max( 1, $wp_query->get('paged') );
|
61 |
+
$this->total_pages = $wp_query->max_num_pages;
|
62 |
+
}
|
63 |
+
}
|
64 |
+
|
65 |
+
protected function render_item( $post ) {
|
66 |
+
return html( 'a', array( 'href' => get_permalink( $post ) ), get_the_title( $post ) );
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
|
71 |
+
class P2P_List_Attachment extends P2P_List_Post {
|
72 |
+
|
73 |
+
protected function render_item( $post ) {
|
74 |
+
return html( 'a', array( 'href' => get_permalink( $post ) ), wp_get_attachment_image( $post->ID, 'thumbnail', false ) );
|
75 |
+
}
|
76 |
+
}
|
77 |
+
|
78 |
+
|
79 |
+
class P2P_List_User extends P2P_List {
|
80 |
+
|
81 |
+
function __construct( $query ) {
|
82 |
+
$qv = $query->query_vars;
|
83 |
+
|
84 |
+
$this->items = $query->get_results();
|
85 |
+
|
86 |
+
if ( isset( $qv['p2p:page'] ) ) {
|
87 |
+
$this->current_page = $qv['p2p:page'];
|
88 |
+
$this->total_pages = ceil( $query->get_total() / $qv['p2p:per_page'] );
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
protected function render_item( $user ) {
|
93 |
+
return html( 'a', array( 'href' => get_author_posts_url( $user->ID ) ), $user->display_name );
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
core/query.php
CHANGED
@@ -100,7 +100,7 @@ class P2P_Query {
|
|
100 |
if ( 'any' == $q['items'] ) {
|
101 |
$search = false;
|
102 |
} else {
|
103 |
-
$search = implode( ',', array_map( 'absint', (
|
104 |
}
|
105 |
|
106 |
$where_parts = array();
|
100 |
if ( 'any' == $q['items'] ) {
|
101 |
$search = false;
|
102 |
} else {
|
103 |
+
$search = implode( ',', array_map( 'absint', _p2p_normalize( $q['items'] ) ) );
|
104 |
}
|
105 |
|
106 |
$where_parts = array();
|
core/side.php
CHANGED
@@ -1,7 +1,5 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
define( 'ADMIN_BOX_PER_PAGE', 5 );
|
4 |
-
|
5 |
abstract class P2P_Side {
|
6 |
|
7 |
public $query_vars;
|
@@ -10,8 +8,8 @@ abstract class P2P_Side {
|
|
10 |
$this->query_vars = $query_vars;
|
11 |
}
|
12 |
|
13 |
-
function get_base_qv() {
|
14 |
-
return $this->query_vars;
|
15 |
}
|
16 |
}
|
17 |
|
@@ -26,9 +24,19 @@ class P2P_Side_Post extends P2P_Side {
|
|
26 |
$this->post_type = $this->query_vars['post_type'];
|
27 |
}
|
28 |
|
29 |
-
function
|
30 |
-
return
|
31 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
'suppress_filters' => false,
|
33 |
'ignore_sticky_posts' => true,
|
34 |
) );
|
@@ -59,56 +67,28 @@ class P2P_Side_Post extends P2P_Side {
|
|
59 |
return new WP_Query( $args );
|
60 |
}
|
61 |
|
62 |
-
function
|
63 |
-
|
64 |
-
'
|
65 |
-
'
|
66 |
-
'
|
|
|
67 |
);
|
68 |
-
}
|
69 |
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
'post_status' => 'any',
|
74 |
-
);
|
75 |
-
|
76 |
-
function get_connections_qv() {
|
77 |
-
return array_merge( self::$admin_box_qv, array(
|
78 |
-
'nopaging' => true
|
79 |
-
) );
|
80 |
-
}
|
81 |
-
|
82 |
-
function get_connectable_qv( $item_id, $page, $search, $to_exclude ) {
|
83 |
-
$qv = array_merge( $this->get_base_qv(), self::$admin_box_qv, array(
|
84 |
-
'posts_per_page' => ADMIN_BOX_PER_PAGE,
|
85 |
-
'paged' => $page,
|
86 |
-
) );
|
87 |
-
|
88 |
-
if ( $search ) {
|
89 |
-
$qv['s'] = $search;
|
90 |
-
}
|
91 |
-
|
92 |
-
$qv['post__not_in'] = $to_exclude;
|
93 |
|
94 |
return $qv;
|
95 |
}
|
96 |
|
97 |
-
/**
|
98 |
-
* @param mixed A post type, a post id, a post object, an array of post ids or of objects.
|
99 |
-
*/
|
100 |
function item_recognize( $arg ) {
|
101 |
-
if ( is_array( $arg ) ) {
|
102 |
-
$arg = reset( $arg );
|
103 |
-
}
|
104 |
-
|
105 |
if ( is_object( $arg ) ) {
|
|
|
|
|
106 |
$post_type = $arg->post_type;
|
107 |
} elseif ( $post_id = (int) $arg ) {
|
108 |
-
$
|
109 |
-
if ( !$post )
|
110 |
-
return false;
|
111 |
-
$post_type = $post->post_type;
|
112 |
} else {
|
113 |
$post_type = $arg;
|
114 |
}
|
@@ -119,12 +99,12 @@ class P2P_Side_Post extends P2P_Side {
|
|
119 |
return in_array( $post_type, $this->post_type );
|
120 |
}
|
121 |
|
122 |
-
|
123 |
-
|
124 |
-
|
|
|
125 |
|
126 |
-
|
127 |
-
return (bool) get_post( $item_id );
|
128 |
}
|
129 |
|
130 |
function item_title( $item ) {
|
@@ -140,6 +120,12 @@ class P2P_Side_Attachment extends P2P_Side_Post {
|
|
140 |
|
141 |
$this->post_type = array( 'attachment' );
|
142 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
143 |
}
|
144 |
|
145 |
|
@@ -169,40 +155,34 @@ class P2P_Side_User extends P2P_Side {
|
|
169 |
return new WP_User_Query( $args );
|
170 |
}
|
171 |
|
172 |
-
function
|
173 |
-
|
174 |
-
'
|
175 |
-
'current_page' => isset( $query->query_vars['_p2p_page'] ) ? $query->query_vars['_p2p_page'] : 1,
|
176 |
-
'total_pages' => ceil( $query->get_total() / ADMIN_BOX_PER_PAGE )
|
177 |
-
);
|
178 |
-
}
|
179 |
|
180 |
-
|
181 |
-
|
182 |
-
}
|
183 |
|
184 |
-
|
185 |
-
|
186 |
-
'
|
187 |
-
'offset' => ADMIN_BOX_PER_PAGE * ( $page - 1 ),
|
188 |
-
'_p2p_page' => $page
|
189 |
-
) );
|
190 |
-
|
191 |
-
if ( $search ) {
|
192 |
-
$qv['search'] = '*' . $search . '*';
|
193 |
}
|
194 |
|
195 |
-
$qv['exclude'] = $to_exclude;
|
196 |
-
|
197 |
return $qv;
|
198 |
}
|
199 |
|
200 |
function item_recognize( $arg ) {
|
201 |
-
return
|
202 |
}
|
203 |
|
204 |
-
function
|
205 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
}
|
207 |
|
208 |
function item_title( $item ) {
|
1 |
<?php
|
2 |
|
|
|
|
|
3 |
abstract class P2P_Side {
|
4 |
|
5 |
public $query_vars;
|
8 |
$this->query_vars = $query_vars;
|
9 |
}
|
10 |
|
11 |
+
function get_base_qv( $q ) {
|
12 |
+
return array_merge( $this->query_vars, $q );
|
13 |
}
|
14 |
}
|
15 |
|
24 |
$this->post_type = $this->query_vars['post_type'];
|
25 |
}
|
26 |
|
27 |
+
private function get_ptype() {
|
28 |
+
return get_post_type_object( $this->post_type[0] );
|
29 |
+
}
|
30 |
+
|
31 |
+
function get_base_qv( $q ) {
|
32 |
+
if ( isset( $q['post_type'] ) && 'any' != $q['post_type'] ) {
|
33 |
+
$common = array_intersect( $this->post_type, (array) $q['post_type'] );
|
34 |
+
|
35 |
+
if ( !$common )
|
36 |
+
unset( $q['post_type'] );
|
37 |
+
}
|
38 |
+
|
39 |
+
return array_merge( $this->query_vars, $q, array(
|
40 |
'suppress_filters' => false,
|
41 |
'ignore_sticky_posts' => true,
|
42 |
) );
|
67 |
return new WP_Query( $args );
|
68 |
}
|
69 |
|
70 |
+
function translate_qv( $qv ) {
|
71 |
+
$map = array(
|
72 |
+
'exclude' => 'post__not_in',
|
73 |
+
'search' => 's',
|
74 |
+
'page' => 'paged',
|
75 |
+
'per_page' => 'posts_per_page'
|
76 |
);
|
|
|
77 |
|
78 |
+
foreach ( $map as $old => $new )
|
79 |
+
if ( isset( $qv["p2p:$old"] ) )
|
80 |
+
$qv[$new] = _p2p_pluck( $qv, "p2p:$old" );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
|
82 |
return $qv;
|
83 |
}
|
84 |
|
|
|
|
|
|
|
85 |
function item_recognize( $arg ) {
|
|
|
|
|
|
|
|
|
86 |
if ( is_object( $arg ) ) {
|
87 |
+
if ( !isset( $arg->post_type ) )
|
88 |
+
return false;
|
89 |
$post_type = $arg->post_type;
|
90 |
} elseif ( $post_id = (int) $arg ) {
|
91 |
+
$post_type = get_post_type( $post_id );
|
|
|
|
|
|
|
92 |
} else {
|
93 |
$post_type = $arg;
|
94 |
}
|
99 |
return in_array( $post_type, $this->post_type );
|
100 |
}
|
101 |
|
102 |
+
function item_id( $arg ) {
|
103 |
+
$post = get_post( $arg );
|
104 |
+
if ( $post )
|
105 |
+
return $post->ID;
|
106 |
|
107 |
+
return false;
|
|
|
108 |
}
|
109 |
|
110 |
function item_title( $item ) {
|
120 |
|
121 |
$this->post_type = array( 'attachment' );
|
122 |
}
|
123 |
+
|
124 |
+
function get_base_qv( $q ) {
|
125 |
+
return array_merge( parent::get_base_qv( $q ), array(
|
126 |
+
'post_status' => 'inherit'
|
127 |
+
) );
|
128 |
+
}
|
129 |
}
|
130 |
|
131 |
|
155 |
return new WP_User_Query( $args );
|
156 |
}
|
157 |
|
158 |
+
function translate_qv( $qv ) {
|
159 |
+
if ( isset( $qv['p2p:exclude'] ) )
|
160 |
+
$qv['exclude'] = _p2p_pluck( $qv, 'p2p:exclude' );
|
|
|
|
|
|
|
|
|
161 |
|
162 |
+
if ( isset( $qv['p2p:search'] ) && $qv['p2p:search'] )
|
163 |
+
$qv['search'] = '*' . _p2p_pluck( $qv, 'p2p:search' ) . '*';
|
|
|
164 |
|
165 |
+
if ( isset( $qv['p2p:page'] ) && $qv['p2p:page'] > 0 ) {
|
166 |
+
$qv['number'] = $qv['p2p:per_page'];
|
167 |
+
$qv['offset'] = $qv['p2p:per_page'] * ( $qv['p2p:page'] - 1 );
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
}
|
169 |
|
|
|
|
|
170 |
return $qv;
|
171 |
}
|
172 |
|
173 |
function item_recognize( $arg ) {
|
174 |
+
return is_a( $arg, 'WP_User' );
|
175 |
}
|
176 |
|
177 |
+
function item_id( $arg ) {
|
178 |
+
if ( $this->item_recognize( $arg ) )
|
179 |
+
return $arg->ID;
|
180 |
+
|
181 |
+
$user = get_user_by( 'id', $arg );
|
182 |
+
if ( $user )
|
183 |
+
return $user->ID;
|
184 |
+
|
185 |
+
return false;
|
186 |
}
|
187 |
|
188 |
function item_title( $item ) {
|
core/type-factory.php
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
<?php
|
2 |
|
3 |
class P2P_Connection_Type_Factory {
|
|
|
4 |
private static $instances = array();
|
5 |
|
6 |
public static function register( $args ) {
|
@@ -68,14 +69,9 @@ class P2P_Connection_Type_Factory {
|
|
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
|
79 |
|
80 |
if ( isset( self::$instances[ $ctype->name ] ) ) {
|
81 |
trigger_error( "Connection type '$ctype->name' is already defined.", E_USER_NOTICE );
|
1 |
<?php
|
2 |
|
3 |
class P2P_Connection_Type_Factory {
|
4 |
+
|
5 |
private static $instances = array();
|
6 |
|
7 |
public static function register( $args ) {
|
69 |
) ) ) ) );
|
70 |
}
|
71 |
|
|
|
|
|
|
|
|
|
|
|
72 |
$args = apply_filters( 'p2p_connection_type_args', $args );
|
73 |
|
74 |
+
$ctype = new P2P_Connection_Type( $args );
|
75 |
|
76 |
if ( isset( self::$instances[ $ctype->name ] ) ) {
|
77 |
trigger_error( "Connection type '$ctype->name' is already defined.", E_USER_NOTICE );
|
core/type.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
class
|
4 |
|
5 |
public $indeterminate = false;
|
6 |
|
@@ -23,6 +23,17 @@ class Generic_Connection_Type {
|
|
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 );
|
@@ -110,14 +121,17 @@ class Generic_Connection_Type {
|
|
110 |
}
|
111 |
|
112 |
/**
|
113 |
-
* Attempt to guess direction based on a
|
114 |
*
|
115 |
-
* @param
|
116 |
* @param bool Whether to return an instance of P2P_Directed_Connection_Type or just the direction
|
117 |
*
|
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;
|
@@ -131,119 +145,28 @@ class Generic_Connection_Type {
|
|
131 |
return false;
|
132 |
}
|
133 |
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
* Populates each of the outer querie's $post objects with a 'connected' property, containing a list of connected posts
|
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 |
-
|
147 |
-
$post_type = $query->get( 'post_type' );
|
148 |
-
if ( empty( $post_type ) )
|
149 |
-
$post_type = 'post';
|
150 |
-
|
151 |
-
$directed = $this->find_direction( $post_type );
|
152 |
-
if ( !$directed )
|
153 |
-
return false;
|
154 |
-
|
155 |
-
$posts = array();
|
156 |
-
|
157 |
-
foreach ( $query->posts as $post ) {
|
158 |
-
$post->$prop_name = array();
|
159 |
-
$posts[ $post->ID ] = $post;
|
160 |
-
}
|
161 |
-
|
162 |
-
// ignore pagination
|
163 |
-
foreach ( array( 'showposts', 'posts_per_page', 'posts_per_archive_page' ) as $disabled_qv ) {
|
164 |
-
if ( isset( $extra_qv[ $disabled_qv ] ) ) {
|
165 |
-
trigger_error( "Can't use '$disabled_qv' in an inner query", E_USER_WARNING );
|
166 |
-
}
|
167 |
-
}
|
168 |
-
$extra_qv['nopaging'] = true;
|
169 |
-
|
170 |
-
$q = $directed->get_connected( array_keys( $posts ), $extra_qv, 'abstract' );
|
171 |
|
172 |
-
foreach (
|
173 |
-
if (
|
174 |
-
$
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
}
|
181 |
-
|
182 |
-
array_push( $posts[ $outer_item_id ]->$prop_name, $inner_item );
|
183 |
}
|
184 |
-
}
|
185 |
-
|
186 |
-
public function get_desc() {
|
187 |
-
foreach ( array( 'from', 'to' ) as $key ) {
|
188 |
-
$$key = $this->side[ $key ]->get_desc();
|
189 |
-
}
|
190 |
-
|
191 |
-
if ( $this->indeterminate )
|
192 |
-
$arrow = '↔';
|
193 |
-
else
|
194 |
-
$arrow = '→';
|
195 |
-
|
196 |
-
$label = "$from $arrow $to";
|
197 |
-
|
198 |
-
$title = $this->title[ 'from' ];
|
199 |
-
|
200 |
-
if ( $title )
|
201 |
-
$label .= " ($title)";
|
202 |
-
|
203 |
-
return $label;
|
204 |
-
}
|
205 |
-
}
|
206 |
-
|
207 |
-
|
208 |
-
class P2P_Connection_Type extends Generic_Connection_Type {
|
209 |
-
|
210 |
-
public function __construct( $args ) {
|
211 |
-
parent::__construct( $args );
|
212 |
|
213 |
-
|
214 |
-
|
215 |
-
if ( !empty( $common ) )
|
216 |
-
$this->indeterminate = true;
|
217 |
-
}
|
218 |
-
|
219 |
-
public function __get( $key ) {
|
220 |
-
if ( 'from' == $key || 'to' == $key )
|
221 |
-
return $this->side[ $key ]->post_type;
|
222 |
-
}
|
223 |
-
|
224 |
-
/**
|
225 |
-
* Get a list of posts connected to other posts connected to a post.
|
226 |
-
*
|
227 |
-
* @param int|array $post_id A post id or array of post ids
|
228 |
-
* @param array $extra_qv Additional query variables to use.
|
229 |
-
*
|
230 |
-
* @return bool|object False on failure; A WP_Query instance on success.
|
231 |
-
*/
|
232 |
-
public function get_related( $post_id, $extra_qv = array() ) {
|
233 |
-
$post_id = (array) $post_id;
|
234 |
-
|
235 |
-
$connected = $this->get_connected( $post_id, $extra_qv );
|
236 |
-
if ( !$connected )
|
237 |
return false;
|
238 |
|
239 |
-
if (
|
240 |
-
return
|
241 |
|
242 |
-
|
243 |
-
|
244 |
-
return $this->get_connected( $connected_ids, array(
|
245 |
-
'post__not_in' => $post_id,
|
246 |
-
) );
|
247 |
}
|
248 |
|
249 |
/** Alias for get_prev() */
|
@@ -285,18 +208,22 @@ class P2P_Connection_Type extends Generic_Connection_Type {
|
|
285 |
* @return bool|object False on failure, post object on success
|
286 |
*/
|
287 |
public function get_adjacent( $from, $to, $which ) {
|
|
|
|
|
|
|
288 |
$directed = $this->find_direction( $to );
|
289 |
if ( !$directed )
|
290 |
return false;
|
291 |
|
292 |
-
|
|
|
293 |
return false;
|
294 |
|
295 |
$p2p_id = $directed->get_p2p_id( $to, $from );
|
296 |
if ( !$p2p_id )
|
297 |
return false;
|
298 |
|
299 |
-
$order = (int) p2p_get_meta( $p2p_id, $
|
300 |
|
301 |
$adjacent = $directed->get_connected( $to, array(
|
302 |
'connected_meta' => array(
|
@@ -305,12 +232,72 @@ class P2P_Connection_Type extends Generic_Connection_Type {
|
|
305 |
'value' => $order + $which
|
306 |
)
|
307 |
)
|
308 |
-
) )
|
309 |
|
310 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
311 |
return false;
|
312 |
|
313 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
314 |
}
|
315 |
}
|
316 |
|
1 |
<?php
|
2 |
|
3 |
+
class P2P_Connection_Type {
|
4 |
|
5 |
public $indeterminate = false;
|
6 |
|
23 |
$this->side[ $direction ] = new $class( _p2p_pluck( $args, $direction . '_query_vars' ) );
|
24 |
}
|
25 |
|
26 |
+
if ( $this->object['from'] == $this->object['to'] ) {
|
27 |
+
if ( 'post' == $this->object['to'] ) {
|
28 |
+
$common = array_intersect( $this->side['from']->post_type, $this->side['to']->post_type );
|
29 |
+
|
30 |
+
if ( !empty( $common ) )
|
31 |
+
$this->indeterminate = true;
|
32 |
+
}
|
33 |
+
} else {
|
34 |
+
$this->self_connections = true;
|
35 |
+
}
|
36 |
+
|
37 |
$this->set_cardinality( _p2p_pluck( $args, 'cardinality' ) );
|
38 |
|
39 |
$this->set_labels( $args );
|
121 |
}
|
122 |
|
123 |
/**
|
124 |
+
* Attempt to guess direction based on a parameter.
|
125 |
*
|
126 |
+
* @param mixed A post type, object or object id.
|
127 |
* @param bool Whether to return an instance of P2P_Directed_Connection_Type or just the direction
|
128 |
*
|
129 |
* @return bool|object|string False on failure, P2P_Directed_Connection_Type instance or direction on success.
|
130 |
*/
|
131 |
public function find_direction( $arg, $instantiate = true ) {
|
132 |
+
if ( is_array( $arg ) )
|
133 |
+
$arg = reset( $arg );
|
134 |
+
|
135 |
foreach ( array( 'from', 'to' ) as $direction ) {
|
136 |
if ( !$this->side[ $direction ]->item_recognize( $arg ) )
|
137 |
continue;
|
145 |
return false;
|
146 |
}
|
147 |
|
148 |
+
// Used in each_connected()
|
149 |
+
private function find_direction_multiple( $post_types ) {
|
150 |
+
$possible_directions = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
151 |
|
152 |
+
foreach ( array( 'from', 'to' ) as $direction ) {
|
153 |
+
if ( 'post' == $this->object[$direction] ) {
|
154 |
+
foreach ( $post_types as $post_type ) {
|
155 |
+
if ( !$this->side[ $direction ]->item_recognize( $post_type ) ) {
|
156 |
+
$possible_directions[] = $direction;
|
157 |
+
break;
|
158 |
+
}
|
159 |
+
}
|
160 |
}
|
|
|
|
|
161 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
162 |
|
163 |
+
if ( empty( $possible_directions ) )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
return false;
|
165 |
|
166 |
+
if ( count( $possible_directions ) > 1 )
|
167 |
+
return 'any';
|
168 |
|
169 |
+
return reset( $possible_directions );
|
|
|
|
|
|
|
|
|
170 |
}
|
171 |
|
172 |
/** Alias for get_prev() */
|
208 |
* @return bool|object False on failure, post object on success
|
209 |
*/
|
210 |
public function get_adjacent( $from, $to, $which ) {
|
211 |
+
|
212 |
+
// The direction needs to be based on the second parameter,
|
213 |
+
// so that it's consistent with $this->connect( $from, $to ) etc.
|
214 |
$directed = $this->find_direction( $to );
|
215 |
if ( !$directed )
|
216 |
return false;
|
217 |
|
218 |
+
$key = $directed->get_orderby_key();
|
219 |
+
if ( !$key )
|
220 |
return false;
|
221 |
|
222 |
$p2p_id = $directed->get_p2p_id( $to, $from );
|
223 |
if ( !$p2p_id )
|
224 |
return false;
|
225 |
|
226 |
+
$order = (int) p2p_get_meta( $p2p_id, $key, true );
|
227 |
|
228 |
$adjacent = $directed->get_connected( $to, array(
|
229 |
'connected_meta' => array(
|
232 |
'value' => $order + $which
|
233 |
)
|
234 |
)
|
235 |
+
), 'abstract' );
|
236 |
|
237 |
+
return _p2p_first( $adjacent->items );
|
238 |
+
}
|
239 |
+
|
240 |
+
/**
|
241 |
+
* Optimized inner query, after the outer query was executed.
|
242 |
+
*
|
243 |
+
* Populates each of the outer querie's $post objects with a 'connected' property, containing a list of connected posts
|
244 |
+
*
|
245 |
+
* @param object|array $items WP_Query instance or list of post objects
|
246 |
+
* @param string|array $extra_qv Additional query vars for the inner query.
|
247 |
+
* @param string $prop_name The name of the property used to store the list of connected items on each post object.
|
248 |
+
*/
|
249 |
+
public function each_connected( $items, $extra_qv = array(), $prop_name = 'connected' ) {
|
250 |
+
if ( is_a( $items, 'WP_Query' ) )
|
251 |
+
$items =& $items->posts;
|
252 |
+
|
253 |
+
if ( empty( $items ) || !is_object( $items[0] ) )
|
254 |
+
return;
|
255 |
+
|
256 |
+
$post_types = array_unique( wp_list_pluck( $items, 'post_type' ) );
|
257 |
+
|
258 |
+
if ( count( $post_types ) > 1 ) {
|
259 |
+
$direction = $this->find_direction_multiple( $post_types );
|
260 |
+
$extra_qv['post_type'] = 'any';
|
261 |
+
} else {
|
262 |
+
$direction = $this->find_direction( $post_types[0], false );
|
263 |
+
}
|
264 |
+
|
265 |
+
if ( !$direction )
|
266 |
return false;
|
267 |
|
268 |
+
$directed = $this->set_direction( $direction );
|
269 |
+
|
270 |
+
// ignore pagination
|
271 |
+
foreach ( array( 'showposts', 'posts_per_page', 'posts_per_archive_page' ) as $disabled_qv ) {
|
272 |
+
if ( isset( $extra_qv[ $disabled_qv ] ) ) {
|
273 |
+
trigger_error( "Can't use '$disabled_qv' in an inner query", E_USER_WARNING );
|
274 |
+
}
|
275 |
+
}
|
276 |
+
$extra_qv['nopaging'] = true;
|
277 |
+
|
278 |
+
$q = $directed->get_connected( $items, $extra_qv, 'abstract' );
|
279 |
+
|
280 |
+
p2p_distribute_connected( $items, $q->items, $prop_name );
|
281 |
+
}
|
282 |
+
|
283 |
+
public function get_desc() {
|
284 |
+
foreach ( array( 'from', 'to' ) as $key ) {
|
285 |
+
$$key = $this->side[ $key ]->get_desc();
|
286 |
+
}
|
287 |
+
|
288 |
+
if ( $this->indeterminate )
|
289 |
+
$arrow = '↔';
|
290 |
+
else
|
291 |
+
$arrow = '→';
|
292 |
+
|
293 |
+
$label = "$from $arrow $to";
|
294 |
+
|
295 |
+
$title = $this->title[ 'from' ];
|
296 |
+
|
297 |
+
if ( $title )
|
298 |
+
$label .= " ($title)";
|
299 |
+
|
300 |
+
return $label;
|
301 |
}
|
302 |
}
|
303 |
|
core/util.php
CHANGED
@@ -9,16 +9,27 @@ function _p2p_expand_direction( $direction ) {
|
|
9 |
}
|
10 |
|
11 |
/** @internal */
|
12 |
-
function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
global $wpdb;
|
14 |
|
15 |
-
if ( isset( $
|
16 |
-
$meta_query = $
|
17 |
}
|
18 |
else {
|
19 |
$meta_query = array();
|
20 |
|
21 |
-
foreach ( $
|
22 |
$meta_query[] = compact( 'key', 'value' );
|
23 |
}
|
24 |
}
|
9 |
}
|
10 |
|
11 |
/** @internal */
|
12 |
+
function _p2p_normalize( $items ) {
|
13 |
+
if ( !is_array( $items ) )
|
14 |
+
$items = array( $items );
|
15 |
+
|
16 |
+
if ( is_object( reset( $items ) ) )
|
17 |
+
$items = wp_list_pluck( $items, 'ID' );
|
18 |
+
|
19 |
+
return $items;
|
20 |
+
}
|
21 |
+
|
22 |
+
/** @internal */
|
23 |
+
function _p2p_meta_sql_helper( $query ) {
|
24 |
global $wpdb;
|
25 |
|
26 |
+
if ( isset( $query[0] ) ) {
|
27 |
+
$meta_query = $query;
|
28 |
}
|
29 |
else {
|
30 |
$meta_query = array();
|
31 |
|
32 |
+
foreach ( $query as $key => $value ) {
|
33 |
$meta_query[] = compact( 'key', 'value' );
|
34 |
}
|
35 |
}
|
core/widget.php
DELETED
@@ -1,98 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class P2P_Widget extends scbWidget {
|
4 |
-
|
5 |
-
protected $defaults = array(
|
6 |
-
'ctype' => false,
|
7 |
-
'listing' => 'connected'
|
8 |
-
);
|
9 |
-
|
10 |
-
static function init() {
|
11 |
-
parent::init( __CLASS__, false, 'p2p' );
|
12 |
-
}
|
13 |
-
|
14 |
-
function __construct() {
|
15 |
-
parent::__construct( 'p2p', __( 'Posts 2 Posts', P2P_TEXTDOMAIN ), array(
|
16 |
-
'description' => __( 'A list of posts connected to the current post', P2P_TEXTDOMAIN )
|
17 |
-
) );
|
18 |
-
}
|
19 |
-
|
20 |
-
function form( $instance ) {
|
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 ] = $ctype->get_desc();
|
31 |
-
}
|
32 |
-
|
33 |
-
echo html( 'p', $this->input( array(
|
34 |
-
'type' => 'select',
|
35 |
-
'name' => 'ctype',
|
36 |
-
'values' => $ctypes,
|
37 |
-
'desc' => __( 'Connection type:', P2P_TEXTDOMAIN )
|
38 |
-
), $instance ) );
|
39 |
-
|
40 |
-
echo html( 'p',
|
41 |
-
__( 'Connection listing:', P2P_TEXTDOMAIN ),
|
42 |
-
'<br>',
|
43 |
-
$this->input( array(
|
44 |
-
'type' => 'radio',
|
45 |
-
'name' => 'listing',
|
46 |
-
'values' => array(
|
47 |
-
'connected' => __( 'connected', P2P_TEXTDOMAIN ),
|
48 |
-
'related' => __( 'related', P2P_TEXTDOMAIN )
|
49 |
-
),
|
50 |
-
), $instance )
|
51 |
-
);
|
52 |
-
}
|
53 |
-
|
54 |
-
function widget( $args, $instance ) {
|
55 |
-
if ( !is_singular() )
|
56 |
-
return;
|
57 |
-
|
58 |
-
$instance = array_merge( $this->defaults, $instance );
|
59 |
-
|
60 |
-
$post_id = get_queried_object_id();
|
61 |
-
|
62 |
-
$ctype = p2p_type( $instance['ctype'] );
|
63 |
-
if ( !$ctype )
|
64 |
-
return;
|
65 |
-
|
66 |
-
$directed = $ctype->find_direction( $post_id );
|
67 |
-
if ( !$directed )
|
68 |
-
return;
|
69 |
-
|
70 |
-
if ( 'related' == $instance['listing'] ) {
|
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() )
|
82 |
-
return;
|
83 |
-
|
84 |
-
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
|
85 |
-
|
86 |
-
extract( $args );
|
87 |
-
|
88 |
-
echo $before_widget;
|
89 |
-
|
90 |
-
if ( ! empty( $title ) )
|
91 |
-
echo $before_title . $title . $after_title;
|
92 |
-
|
93 |
-
p2p_list_posts( $connected );
|
94 |
-
|
95 |
-
echo $after_widget;
|
96 |
-
}
|
97 |
-
}
|
98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lang/posts-to-posts-ro_RO.mo
CHANGED
Binary file
|
lang/posts-to-posts-ro_RO.po
CHANGED
@@ -7,8 +7,8 @@ msgid ""
|
|
7 |
msgstr ""
|
8 |
"Project-Id-Version: Posts 2 Posts\n"
|
9 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
|
10 |
-
"POT-Creation-Date: 2012-04-
|
11 |
-
"PO-Revision-Date: 2012-04-
|
12 |
"Last-Translator: scribu <mail@scribu.net>\n"
|
13 |
"Language-Team: ROMANIAN <LL@li.org>\n"
|
14 |
"Language: \n"
|
@@ -24,37 +24,37 @@ msgstr "(de la)"
|
|
24 |
msgid " (to)"
|
25 |
msgstr "(la)"
|
26 |
|
27 |
-
#: admin/box.php:
|
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:
|
32 |
msgid "Create connections:"
|
33 |
msgstr "Creează conexiuni:"
|
34 |
|
35 |
-
#: admin/box.php:
|
36 |
msgid "View All"
|
37 |
msgstr "Vezi toate"
|
38 |
|
39 |
-
#: admin/box.php:
|
40 |
msgid "Search"
|
41 |
msgstr "Căutare"
|
42 |
|
43 |
-
#: admin/box.php:
|
44 |
msgid "previous"
|
45 |
msgstr "anterioare"
|
46 |
|
47 |
-
#: admin/box.php:
|
48 |
msgid "next"
|
49 |
msgstr "următoare"
|
50 |
|
51 |
-
#: admin/box.php:
|
52 |
msgid "of"
|
53 |
msgstr "din"
|
54 |
|
55 |
-
#: admin/box.php:
|
56 |
-
msgid "Can't create connection
|
57 |
-
msgstr "Conexiunea nu poate fi creat
|
58 |
|
59 |
#: admin/fields.php:13
|
60 |
msgid "Create connection"
|
@@ -70,7 +70,7 @@ msgstr "Șterge conexiune"
|
|
70 |
|
71 |
#: admin/tools.php:7
|
72 |
msgid "Connection Types"
|
73 |
-
msgstr "Tipuri de conexiuni
|
74 |
|
75 |
#: admin/tools.php:31
|
76 |
msgid "Upgraded %d connections."
|
@@ -108,53 +108,53 @@ msgstr "Convertește într-un tip de conexiune înregistrat:"
|
|
108 |
msgid "Go"
|
109 |
msgstr "Go"
|
110 |
|
111 |
-
#: core/
|
112 |
-
msgid "Users"
|
113 |
-
msgstr "Utilizatori"
|
114 |
-
|
115 |
-
#: core/side.php:158
|
116 |
-
msgid "User"
|
117 |
-
msgstr "Utilizator"
|
118 |
-
|
119 |
-
#: core/side.php:159
|
120 |
-
msgid "Search Users"
|
121 |
-
msgstr "Caută utilizatori"
|
122 |
-
|
123 |
-
#: core/side.php:160
|
124 |
-
msgid "No users found."
|
125 |
-
msgstr "Niciun utilizator găsit."
|
126 |
-
|
127 |
-
#: core/type.php:77
|
128 |
-
msgid "Connected %s"
|
129 |
-
msgstr "%s conectate"
|
130 |
-
|
131 |
-
#: core/widget.php:15
|
132 |
msgid "Posts 2 Posts"
|
133 |
msgstr "Posts 2 Posts"
|
134 |
|
135 |
-
#: core/
|
136 |
msgid "A list of posts connected to the current post"
|
137 |
msgstr "O lista de postări conectate la postarea curentă"
|
138 |
|
139 |
-
#: core/
|
|
|
|
|
|
|
|
|
140 |
msgid "Connection type:"
|
141 |
msgstr "Tipul conexiunii:"
|
142 |
|
143 |
-
#: core/
|
144 |
msgid "Connection listing:"
|
145 |
-
msgstr "
|
146 |
|
147 |
-
#: core/
|
148 |
msgid "connected"
|
149 |
msgstr "conectate"
|
150 |
|
151 |
-
#: core/
|
152 |
msgid "related"
|
153 |
msgstr "înrudite"
|
154 |
|
155 |
-
#: core/
|
156 |
-
msgid "
|
157 |
-
msgstr "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
158 |
|
159 |
#: scb/AdminPage.php:172
|
160 |
msgid "Settings <strong>saved</strong>."
|
@@ -169,6 +169,9 @@ msgstr "Salvează schimbările"
|
|
169 |
msgid "Settings"
|
170 |
msgstr "Setări"
|
171 |
|
|
|
|
|
|
|
172 |
#~ msgid "Recent"
|
173 |
#~ msgstr "Recente"
|
174 |
|
7 |
msgstr ""
|
8 |
"Project-Id-Version: Posts 2 Posts\n"
|
9 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
|
10 |
+
"POT-Creation-Date: 2012-04-15 23:11:12+00:00\n"
|
11 |
+
"PO-Revision-Date: 2012-04-16 02:15+0200\n"
|
12 |
"Last-Translator: scribu <mail@scribu.net>\n"
|
13 |
"Language-Team: ROMANIAN <LL@li.org>\n"
|
14 |
"Language: \n"
|
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:129
|
32 |
msgid "Create connections:"
|
33 |
msgstr "Creează conexiuni:"
|
34 |
|
35 |
+
#: admin/box.php:138
|
36 |
msgid "View All"
|
37 |
msgstr "Vezi toate"
|
38 |
|
39 |
+
#: admin/box.php:143
|
40 |
msgid "Search"
|
41 |
msgstr "Căutare"
|
42 |
|
43 |
+
#: admin/box.php:220
|
44 |
msgid "previous"
|
45 |
msgstr "anterioare"
|
46 |
|
47 |
+
#: admin/box.php:221
|
48 |
msgid "next"
|
49 |
msgstr "următoare"
|
50 |
|
51 |
+
#: admin/box.php:222
|
52 |
msgid "of"
|
53 |
msgstr "din"
|
54 |
|
55 |
+
#: admin/box.php:261
|
56 |
+
msgid "Can't create connection: %s"
|
57 |
+
msgstr "Conexiunea nu poate fi creată: %s"
|
58 |
|
59 |
#: admin/fields.php:13
|
60 |
msgid "Create connection"
|
70 |
|
71 |
#: admin/tools.php:7
|
72 |
msgid "Connection Types"
|
73 |
+
msgstr "Tipuri de conexiuni"
|
74 |
|
75 |
#: admin/tools.php:31
|
76 |
msgid "Upgraded %d connections."
|
108 |
msgid "Go"
|
109 |
msgstr "Go"
|
110 |
|
111 |
+
#: core/extra.php:16
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
msgid "Posts 2 Posts"
|
113 |
msgstr "Posts 2 Posts"
|
114 |
|
115 |
+
#: core/extra.php:17
|
116 |
msgid "A list of posts connected to the current post"
|
117 |
msgstr "O lista de postări conectate la postarea curentă"
|
118 |
|
119 |
+
#: core/extra.php:37
|
120 |
+
msgid "Title:"
|
121 |
+
msgstr "Titlu:"
|
122 |
+
|
123 |
+
#: core/extra.php:44
|
124 |
msgid "Connection type:"
|
125 |
msgstr "Tipul conexiunii:"
|
126 |
|
127 |
+
#: core/extra.php:48
|
128 |
msgid "Connection listing:"
|
129 |
+
msgstr "Conexiuni de listat:"
|
130 |
|
131 |
+
#: core/extra.php:54
|
132 |
msgid "connected"
|
133 |
msgstr "conectate"
|
134 |
|
135 |
+
#: core/extra.php:55
|
136 |
msgid "related"
|
137 |
msgstr "înrudite"
|
138 |
|
139 |
+
#: core/side.php:129
|
140 |
+
msgid "Users"
|
141 |
+
msgstr "Utilizatori"
|
142 |
+
|
143 |
+
#: core/side.php:138
|
144 |
+
msgid "User"
|
145 |
+
msgstr "Utilizator"
|
146 |
+
|
147 |
+
#: core/side.php:139
|
148 |
+
msgid "Search Users"
|
149 |
+
msgstr "Caută utilizatori"
|
150 |
+
|
151 |
+
#: core/side.php:140
|
152 |
+
msgid "No users found."
|
153 |
+
msgstr "Niciun utilizator găsit."
|
154 |
+
|
155 |
+
#: core/type.php:88
|
156 |
+
msgid "Connected %s"
|
157 |
+
msgstr "%s conectate"
|
158 |
|
159 |
#: scb/AdminPage.php:172
|
160 |
msgid "Settings <strong>saved</strong>."
|
169 |
msgid "Settings"
|
170 |
msgstr "Setări"
|
171 |
|
172 |
+
#~ msgid "Related %s"
|
173 |
+
#~ msgstr "%s înrudite"
|
174 |
+
|
175 |
#~ msgid "Recent"
|
176 |
#~ msgstr "Recente"
|
177 |
|
lang/posts-to-posts.pot
CHANGED
@@ -4,7 +4,7 @@ msgid ""
|
|
4 |
msgstr ""
|
5 |
"Project-Id-Version: \n"
|
6 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
|
7 |
-
"POT-Creation-Date: 2012-04-
|
8 |
"MIME-Version: 1.0\n"
|
9 |
"Content-Type: text/plain; charset=UTF-8\n"
|
10 |
"Content-Transfer-Encoding: 8bit\n"
|
@@ -20,36 +20,36 @@ msgstr ""
|
|
20 |
msgid " (to)"
|
21 |
msgstr ""
|
22 |
|
23 |
-
#: admin/box.php:
|
24 |
msgid "Are you sure you want to delete all connections?"
|
25 |
msgstr ""
|
26 |
|
27 |
-
#: admin/box.php:
|
28 |
msgid "Create connections:"
|
29 |
msgstr ""
|
30 |
|
31 |
-
#: admin/box.php:
|
32 |
msgid "View All"
|
33 |
msgstr ""
|
34 |
|
35 |
-
#: admin/box.php:
|
36 |
msgid "Search"
|
37 |
msgstr ""
|
38 |
|
39 |
-
#: admin/box.php:
|
40 |
msgid "previous"
|
41 |
msgstr ""
|
42 |
|
43 |
-
#: admin/box.php:
|
44 |
msgid "next"
|
45 |
msgstr ""
|
46 |
|
47 |
-
#: admin/box.php:
|
48 |
msgid "of"
|
49 |
msgstr ""
|
50 |
|
51 |
-
#: admin/box.php:
|
52 |
-
msgid "Can't create connection
|
53 |
msgstr ""
|
54 |
|
55 |
#: admin/fields.php:13
|
@@ -106,52 +106,52 @@ msgstr ""
|
|
106 |
msgid "Go"
|
107 |
msgstr ""
|
108 |
|
109 |
-
#: core/
|
110 |
-
msgid "
|
111 |
msgstr ""
|
112 |
|
113 |
-
#: core/
|
114 |
-
msgid "
|
115 |
msgstr ""
|
116 |
|
117 |
-
#: core/
|
118 |
-
msgid "
|
119 |
msgstr ""
|
120 |
|
121 |
-
#: core/
|
122 |
-
msgid "
|
123 |
msgstr ""
|
124 |
|
125 |
-
#: core/
|
126 |
-
msgid "
|
127 |
msgstr ""
|
128 |
|
129 |
-
#: core/
|
130 |
-
msgid "
|
131 |
msgstr ""
|
132 |
|
133 |
-
#: core/
|
134 |
-
msgid "
|
135 |
msgstr ""
|
136 |
|
137 |
-
#: core/
|
138 |
-
msgid "
|
139 |
msgstr ""
|
140 |
|
141 |
-
#: core/
|
142 |
-
msgid "
|
143 |
msgstr ""
|
144 |
|
145 |
-
#: core/
|
146 |
-
msgid "
|
147 |
msgstr ""
|
148 |
|
149 |
-
#: core/
|
150 |
-
msgid "
|
151 |
msgstr ""
|
152 |
|
153 |
-
#: core/
|
154 |
-
msgid "
|
155 |
msgstr ""
|
156 |
|
157 |
#: scb/AdminPage.php:172
|
4 |
msgstr ""
|
5 |
"Project-Id-Version: \n"
|
6 |
"Report-Msgid-Bugs-To: http://wordpress.org/tag/p2p\n"
|
7 |
+
"POT-Creation-Date: 2012-04-15 23:11:12+00:00\n"
|
8 |
"MIME-Version: 1.0\n"
|
9 |
"Content-Type: text/plain; charset=UTF-8\n"
|
10 |
"Content-Transfer-Encoding: 8bit\n"
|
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:129
|
28 |
msgid "Create connections:"
|
29 |
msgstr ""
|
30 |
|
31 |
+
#: admin/box.php:138
|
32 |
msgid "View All"
|
33 |
msgstr ""
|
34 |
|
35 |
+
#: admin/box.php:143
|
36 |
msgid "Search"
|
37 |
msgstr ""
|
38 |
|
39 |
+
#: admin/box.php:220
|
40 |
msgid "previous"
|
41 |
msgstr ""
|
42 |
|
43 |
+
#: admin/box.php:221
|
44 |
msgid "next"
|
45 |
msgstr ""
|
46 |
|
47 |
+
#: admin/box.php:222
|
48 |
msgid "of"
|
49 |
msgstr ""
|
50 |
|
51 |
+
#: admin/box.php:261
|
52 |
+
msgid "Can't create connection: %s"
|
53 |
msgstr ""
|
54 |
|
55 |
#: admin/fields.php:13
|
106 |
msgid "Go"
|
107 |
msgstr ""
|
108 |
|
109 |
+
#: core/extra.php:16
|
110 |
+
msgid "Posts 2 Posts"
|
111 |
msgstr ""
|
112 |
|
113 |
+
#: core/extra.php:17
|
114 |
+
msgid "A list of posts connected to the current post"
|
115 |
msgstr ""
|
116 |
|
117 |
+
#: core/extra.php:37
|
118 |
+
msgid "Title:"
|
119 |
msgstr ""
|
120 |
|
121 |
+
#: core/extra.php:44
|
122 |
+
msgid "Connection type:"
|
123 |
msgstr ""
|
124 |
|
125 |
+
#: core/extra.php:48
|
126 |
+
msgid "Connection listing:"
|
127 |
msgstr ""
|
128 |
|
129 |
+
#: core/extra.php:54
|
130 |
+
msgid "connected"
|
131 |
msgstr ""
|
132 |
|
133 |
+
#: core/extra.php:55
|
134 |
+
msgid "related"
|
135 |
msgstr ""
|
136 |
|
137 |
+
#: core/side.php:129
|
138 |
+
msgid "Users"
|
139 |
msgstr ""
|
140 |
|
141 |
+
#: core/side.php:138
|
142 |
+
msgid "User"
|
143 |
msgstr ""
|
144 |
|
145 |
+
#: core/side.php:139
|
146 |
+
msgid "Search Users"
|
147 |
msgstr ""
|
148 |
|
149 |
+
#: core/side.php:140
|
150 |
+
msgid "No users found."
|
151 |
msgstr ""
|
152 |
|
153 |
+
#: core/type.php:88
|
154 |
+
msgid "Connected %s"
|
155 |
msgstr ""
|
156 |
|
157 |
#: scb/AdminPage.php:172
|
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
|
@@ -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 |
|
@@ -39,11 +39,12 @@ function _p2p_init() {
|
|
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', '
|
44 |
) );
|
45 |
|
46 |
P2P_Widget::init();
|
|
|
47 |
|
48 |
if ( is_admin() ) {
|
49 |
_p2p_load_files( "$base/admin", array(
|
2 |
/*
|
3 |
Plugin Name: Posts 2 Posts
|
4 |
Description: Create many-to-many relationships between all types of posts.
|
5 |
+
Version: 1.3
|
6 |
Author: scribu
|
7 |
Author URI: http://scribu.net/
|
8 |
Plugin URI: http://scribu.net/wordpress/posts-to-posts
|
26 |
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
27 |
*/
|
28 |
|
29 |
+
define( 'P2P_PLUGIN_VERSION', '1.3-beta' );
|
30 |
|
31 |
define( 'P2P_TEXTDOMAIN', 'posts-to-posts' );
|
32 |
|
39 |
|
40 |
_p2p_load_files( "$base/core", array(
|
41 |
'storage', 'query', 'query-post', 'query-user', 'url-query',
|
42 |
+
'util', 'side', 'list', 'type-factory', 'type', 'directed-type',
|
43 |
+
'api', 'extra'
|
44 |
) );
|
45 |
|
46 |
P2P_Widget::init();
|
47 |
+
P2P_Shortcodes::init();
|
48 |
|
49 |
if ( is_admin() ) {
|
50 |
_p2p_load_files( "$base/admin", array(
|
readme.txt
CHANGED
@@ -2,8 +2,8 @@
|
|
2 |
Contributors: scribu, ciobi
|
3 |
Tags: connections, custom post types, relationships, many-to-many, users
|
4 |
Requires at least: 3.2
|
5 |
-
Tested up to: 3.
|
6 |
-
Stable tag: 1.
|
7 |
|
8 |
Efficient many-to-many connections between posts, pages, custom post types, users.
|
9 |
|
@@ -11,9 +11,10 @@ Efficient many-to-many connections between posts, pages, custom post types, user
|
|
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 |
-
*
|
|
|
|
|
17 |
|
18 |
Additionally, you can create many-to-many relationships between posts and users. So, you could also implement:
|
19 |
|
@@ -50,6 +51,14 @@ Make sure your host is running PHP 5. The only foolproof way to do this is to ad
|
|
50 |
|
51 |
== Changelog ==
|
52 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
= 1.2 =
|
54 |
* added Tools -> Connection Types admin screen
|
55 |
* fixed migration script
|
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.4
|
6 |
+
Stable tag: 1.3
|
7 |
|
8 |
Efficient many-to-many connections between posts, pages, custom post types, users.
|
9 |
|
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 |
* manually curated lists of related posts
|
15 |
+
* post series
|
16 |
+
* products connected to retailers
|
17 |
+
* etc.
|
18 |
|
19 |
Additionally, you can create many-to-many relationships between posts and users. So, you could also implement:
|
20 |
|
51 |
|
52 |
== Changelog ==
|
53 |
|
54 |
+
= 1.3 =
|
55 |
+
* allow passing entire objects to get_connected(), connect() etc.
|
56 |
+
* made get_related() work with posts-to-users connections
|
57 |
+
* made each_connected() work with simple array of posts
|
58 |
+
* introduced [p2p_connected] and [p2p_related] shortcodes
|
59 |
+
* allow 'default' parameter in 'fields' array
|
60 |
+
* [more info](http://scribu.net/wordpress/posts-to-posts/p2p-1-3.html)
|
61 |
+
|
62 |
= 1.2 =
|
63 |
* added Tools -> Connection Types admin screen
|
64 |
* fixed migration script
|
scb/Forms.php
CHANGED
@@ -9,6 +9,9 @@ class scbForms {
|
|
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':
|
@@ -433,7 +436,12 @@ class scbForms {
|
|
433 |
$key = (array) $args['name'];
|
434 |
$key = end( $key );
|
435 |
|
436 |
-
$value = get_metadata( $meta_type, $object_id, $key
|
|
|
|
|
|
|
|
|
|
|
437 |
|
438 |
return self::input_with_value( $args, $value );
|
439 |
}
|
@@ -511,9 +519,7 @@ class scbForm {
|
|
511 |
}
|
512 |
|
513 |
function input( $args ) {
|
514 |
-
$
|
515 |
-
|
516 |
-
$value = scbForms::get_value( $args['name'], $this->data, $default );
|
517 |
|
518 |
if ( !empty( $this->prefix ) ) {
|
519 |
$args['name'] = array_merge( $this->prefix, (array) $args['name'] );
|
9 |
protected static $cur_name;
|
10 |
|
11 |
function input_with_value( $args, $value ) {
|
12 |
+
if ( is_null( $value ) && isset( $args['default'] ) )
|
13 |
+
$value = $args['default'];
|
14 |
+
|
15 |
if ( !is_null( $value ) ) {
|
16 |
switch ( $args['type'] ) {
|
17 |
case 'select':
|
436 |
$key = (array) $args['name'];
|
437 |
$key = end( $key );
|
438 |
|
439 |
+
$value = get_metadata( $meta_type, $object_id, $key );
|
440 |
+
|
441 |
+
if ( empty( $value ) )
|
442 |
+
$value = null;
|
443 |
+
elseif( $single )
|
444 |
+
$value = reset( $value );
|
445 |
|
446 |
return self::input_with_value( $args, $value );
|
447 |
}
|
519 |
}
|
520 |
|
521 |
function input( $args ) {
|
522 |
+
$value = scbForms::get_value( $args['name'], $this->data );
|
|
|
|
|
523 |
|
524 |
if ( !empty( $this->prefix ) ) {
|
525 |
$args['name'] = array_merge( $this->prefix, (array) $args['name'] );
|
scb/load.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
$GLOBALS['_scb_data'] = array(
|
4 |
'scbUtil', 'scbOptions', 'scbForms', 'scbTable',
|
5 |
'scbWidget', 'scbAdminPage', 'scbBoxesPage',
|
6 |
'scbCron', 'scbHooks',
|
1 |
<?php
|
2 |
|
3 |
+
$GLOBALS['_scb_data'] = array( 53, __FILE__, array(
|
4 |
'scbUtil', 'scbOptions', 'scbForms', 'scbTable',
|
5 |
'scbWidget', 'scbAdminPage', 'scbBoxesPage',
|
6 |
'scbCron', 'scbHooks',
|
screenshot-1.png
CHANGED
Binary file
|
screenshot-2.png
CHANGED
Binary file
|