1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* . |
5
|
|
|
* |
6
|
|
|
* @package wordpoints-hooks-api |
7
|
|
|
* @since 1. |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
|
11
|
|
|
interface WordPoints_Hook_Event_RetroactiveI { |
12
|
|
|
public function get_retroactive_description(); |
13
|
|
|
} |
14
|
|
|
|
15
|
|
|
|
16
|
|
|
//public function modify_retroactive_query( WordPoints_Hook_Retroactive_QueryI $query ) { |
|
|
|
|
17
|
|
|
// $query->add_condition( array( 'field' => 'comment_approved', 'value' => '1' ) ); |
18
|
|
|
//} |
19
|
|
|
// |
20
|
|
|
//public function modify_retroactive_query( WordPoints_Hook_Retroactive_QueryI $query ) { |
21
|
|
|
// $query->add_condition( array( 'field' => 'post_status', 'value' => 'publish' ) ); |
22
|
|
|
//} |
23
|
|
|
|
24
|
|
|
|
25
|
|
|
|
26
|
|
|
//public function modify_retroactive_query( WordPoints_Hook_Retroactive_QueryI $query ) { |
|
|
|
|
27
|
|
|
// |
28
|
|
|
// $reaction = $query->get_reaction(); |
29
|
|
|
// |
30
|
|
|
// $this->validator = $query->get_validator(); |
31
|
|
|
// |
32
|
|
|
// $conditions = $reaction->get_meta( 'conditions' ); |
33
|
|
|
// |
34
|
|
|
//// $conditions = $this->validate_conditions( $conditions ); |
35
|
|
|
// var_dump( __FUNCTION__,$conditions ); |
36
|
|
|
// $this->_modify_retroactive_query( $query, $conditions ); |
37
|
|
|
//} |
38
|
|
|
// |
39
|
|
|
//public function _modify_retroactive_query( WordPoints_Hook_Retroactive_QueryI $query, $args ) { |
40
|
|
|
// |
41
|
|
|
// foreach ( $args as $arg_slug => $sub_args ) { |
42
|
|
|
// |
43
|
|
|
// $query->arg_hierarchy_push( $arg_slug ); |
44
|
|
|
// |
45
|
|
|
// if ( isset( $sub_args['_conditions'] ) ) { |
46
|
|
|
// |
47
|
|
|
// foreach ( $sub_args['_conditions'] as $condition ) { |
48
|
|
|
// |
49
|
|
|
// $condition_obj = $this->conditions->get( |
50
|
|
|
// $condition['type'] |
51
|
|
|
// ); |
52
|
|
|
// |
53
|
|
|
// if ( $condition_obj instanceof WordPoints_Hook_Retroactive_Query_ModifierI ) { |
54
|
|
|
// |
55
|
|
|
// $condition_obj->modify_retroactive_query( |
56
|
|
|
// $query |
57
|
|
|
// , $condition['settings'] |
58
|
|
|
// ); |
59
|
|
|
// |
60
|
|
|
// } else { |
61
|
|
|
// $query->add_condition( $condition['settings'] ); |
62
|
|
|
// } |
63
|
|
|
// } |
64
|
|
|
// |
65
|
|
|
// unset( $sub_args['_conditions'] ); |
66
|
|
|
// } |
67
|
|
|
// |
68
|
|
|
// $this->_modify_retroactive_query( $query, $sub_args ); |
69
|
|
|
// |
70
|
|
|
// $query->arg_hierarchy_pop( $arg_slug ); |
71
|
|
|
// } |
72
|
|
|
//} |
73
|
|
|
|
74
|
|
|
|
75
|
|
|
interface WordPoints_Hook_Reactor_RetroactiveI extends WordPoints_Hook_Retroactive_Query_ModifierI { |
76
|
|
|
public function retroactive_hit( $target, array $records, WordPoints_Hook_Event_RetroactiveI $event, WordPoints_Hook_ReactionI $reaction ); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
abstract class WordPoints_Hook_Reactor_Retroactive implements WordPoints_Hook_Reactor_RetroactiveI { |
80
|
|
|
|
81
|
|
|
public function modify_retroactive_query( WordPoints_Hook_Retroactive_QueryI $query ) { |
82
|
|
|
|
83
|
|
|
$query->set_target( $query->get_reaction()->get_meta( 'target' ) ); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
public function reverse_hits() { |
87
|
|
|
// if ( ! $logs ) { |
|
|
|
|
88
|
|
|
// // Check if this reversal was part of a retroactive fire. |
89
|
|
|
// if ( $event instanceof WordPoints_Hook_Event_RetroactiveI ) { |
90
|
|
|
// $this->reverse_retroactive_hits( $args, $event ); |
91
|
|
|
// } |
92
|
|
|
// |
93
|
|
|
// return; |
94
|
|
|
// } |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* @since 1.0.0 |
99
|
|
|
*/ |
100
|
|
|
public function retroactive_hit( $target, array $records, WordPoints_Hook_Event_RetroactiveI $event, WordPoints_Hook_ReactionI $reaction ) { |
101
|
|
|
|
102
|
|
|
$count = count( $records ); |
103
|
|
|
|
104
|
|
|
wordpoints_alter_points( |
105
|
|
|
$target |
106
|
|
|
, $reaction->get_meta( 'points' ) * $count |
107
|
|
|
, $reaction->get_meta( 'points_type' ) |
108
|
|
|
, 'retroactive_' . $reaction->get_event_slug() |
109
|
|
|
, array( 'count' => $count ) |
110
|
|
|
, $event->get_retroactive_description( $reaction ) |
|
|
|
|
111
|
|
|
); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* |
116
|
|
|
* |
117
|
|
|
* @since 1. |
118
|
|
|
* |
119
|
|
|
* @param WordPoints_Hook_Event_Args $args |
120
|
|
|
* @param WordPoints_Hook_Event_RetroactiveI $event |
121
|
|
|
*/ |
122
|
|
|
protected function reverse_retroactive_hits( |
123
|
|
|
WordPoints_Hook_Event_Args $args, |
124
|
|
|
WordPoints_Hook_Event_RetroactiveI $event |
125
|
|
|
) { |
126
|
|
|
|
127
|
|
|
// TODO do we even need to do this? |
128
|
|
|
$query = new WordPoints_Points_Logs_Query( |
129
|
|
|
array( |
130
|
|
|
'log_type' => "retroactive_{$event}", |
131
|
|
|
'meta_query' => array( |
132
|
|
|
array( |
133
|
|
|
'key' => 'auto_reversed', |
134
|
|
|
'value' => $args->get_entity_id(), |
135
|
|
|
), |
136
|
|
|
), |
137
|
|
|
) |
138
|
|
|
); |
139
|
|
|
|
140
|
|
|
$logs = $query->get(); |
141
|
|
|
|
142
|
|
|
if ( ! $logs ) { |
143
|
|
|
return; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
foreach ( $logs as $log ) { |
147
|
|
|
|
148
|
|
|
wordpoints_alter_points( |
149
|
|
|
$log->user_id |
150
|
|
|
, - ( $log->points / wordpoints_get_points_log_meta( $log->id, 'count', true ) ) |
151
|
|
|
, $log->points_type |
152
|
|
|
, "reverse_{$event}" |
153
|
|
|
, array( 'original_log_id' => $log->id ) |
154
|
|
|
, $args->get_description() |
155
|
|
|
); |
156
|
|
|
|
157
|
|
|
wordpoints_add_points_log_meta( $log->id, 'auto_reversed', $args->get_entity_id() ); |
158
|
|
|
} |
159
|
|
|
} |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
class WordPoints_Hook_Retroactive_Query implements WordPoints_Hook_Retroactive_QueryI { |
163
|
|
|
|
164
|
|
|
protected $reaction; |
165
|
|
|
|
166
|
|
|
protected $arg_hierarchy = array(); |
167
|
|
|
|
168
|
|
|
protected $validator; |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* |
172
|
|
|
* |
173
|
|
|
* @since 1. |
174
|
|
|
* |
175
|
|
|
* @var WordPoints_Hierarchy |
176
|
|
|
*/ |
177
|
|
|
protected $query; |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* |
181
|
|
|
* |
182
|
|
|
* @since 1. |
183
|
|
|
* |
184
|
|
|
* @var WordPoints_Hierarchy |
185
|
|
|
*/ |
186
|
|
|
protected $queries; |
187
|
|
|
|
188
|
|
|
/** |
189
|
|
|
* |
190
|
|
|
* |
191
|
|
|
* @since 1. |
192
|
|
|
* |
193
|
|
|
* @var WordPoints_EntityishI |
194
|
|
|
*/ |
195
|
|
|
protected $parent_arg; |
196
|
|
|
|
197
|
|
|
protected $results; |
198
|
|
|
|
199
|
|
|
public function __construct( WordPoints_Hook_ReactionI $reaction ) { |
200
|
|
|
|
201
|
|
|
$this->reaction = $reaction; |
202
|
|
|
$this->arg_hierarchy = new WordPoints_Hierarchy( 'sub_args' ); |
|
|
|
|
203
|
|
|
$this->hooks = wordpoints_hooks(); |
|
|
|
|
204
|
|
|
$this->entities = wordpoints_entities(); |
|
|
|
|
205
|
|
|
$this->validator = new WordPoints_Hook_Reaction_Validator( $reaction, true ); |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
public function get_reaction() { |
209
|
|
|
return $this->reaction; |
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
public function get_validator() { |
213
|
|
|
return $this->validator; |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
public function get_results() { |
217
|
|
|
|
218
|
|
|
if ( ! isset( $this->results ) ) { |
219
|
|
|
|
220
|
|
|
$this->execute(); |
221
|
|
|
|
222
|
|
|
if ( $this->validator->had_errors() ) { |
223
|
|
|
$this->results = $this->validator; |
224
|
|
|
} |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
return $this->results; |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
protected function execute() { |
231
|
|
|
|
232
|
|
|
try { |
233
|
|
|
|
234
|
|
|
$this->prepare_query(); |
235
|
|
|
$this->perform_query(); |
236
|
|
|
$this->filter_results(); |
237
|
|
|
$this->group_results(); |
238
|
|
|
|
239
|
|
|
} catch ( WordPoints_Hook_Validator_Exception $e ) { |
|
|
|
|
240
|
|
|
unset( $e ); |
241
|
|
|
} |
242
|
|
|
} |
243
|
|
|
|
244
|
|
|
protected function prepare_query() { |
245
|
|
|
|
246
|
|
|
$event_slug = $this->reaction->get_event_slug(); |
247
|
|
|
|
248
|
|
|
$events = $this->hooks->get_sub_app( 'events' ); |
249
|
|
|
$event = $events->get( $event_slug ); |
250
|
|
|
|
251
|
|
|
if ( ! ( $event instanceof WordPoints_Hook_Event_RetroactiveI ) ) { |
252
|
|
|
$this->validator->add_error( 'invalid hook' ); |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
foreach ( $events->get_sub_app( 'args' )->get_children( $event_slug ) as $arg ) { |
256
|
|
|
$this->arg_hierarchy_push( // TODO |
257
|
|
|
$arg |
258
|
|
|
); |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
if ( $event instanceof WordPoints_Hook_Retroactive_Query_ModifierI ) { |
262
|
|
|
$event->modify_retroactive_query( $this ); |
263
|
|
|
$this->reset(); |
264
|
|
|
} |
265
|
|
|
|
266
|
|
|
$reactor = $this->hooks->get_sub_app( 'reactors' )->get( $this->reaction->get_reactor_slug() ); |
267
|
|
|
|
268
|
|
|
$reactor->modify_retroactive_query( $this ); |
269
|
|
|
$this->reset(); |
270
|
|
|
|
271
|
|
|
foreach ( $this->hooks->get_sub_app( 'extensions' )->get_all() as $extension ) { |
272
|
|
|
|
273
|
|
|
if ( $extension instanceof WordPoints_Hook_Retroactive_Query_ModifierI ) { |
274
|
|
|
$extension->modify_retroactive_query( $this ); |
275
|
|
|
$this->reset(); |
276
|
|
|
} |
277
|
|
|
} |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
protected function perform_query() { |
281
|
|
|
|
282
|
|
|
$this->queries = new WordPoints_Hierarchy( 'sub_queries' ); |
283
|
|
|
$this->consolidate_queries( array( $this->arg_hierarchy->get() ) ); |
|
|
|
|
284
|
|
|
unset( $this->query ); |
285
|
|
|
|
286
|
|
|
$this->queries->reset(); |
287
|
|
|
|
288
|
|
|
// Find the tip of a query. |
289
|
|
|
$this->results = $this->execute_queries( $this->queries->get() ); |
290
|
|
|
|
291
|
|
|
if ( is_wp_error( $this->results ) ) { |
292
|
|
|
$this->validator->add_error( $this->results ); |
293
|
|
|
} |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
protected function consolidate_queries( $arg_hierarchy, $storage_type = null ) { |
297
|
|
|
|
298
|
|
|
foreach ( $arg_hierarchy as $data ) { |
299
|
|
|
$this->consolidate_query( $data ); |
300
|
|
|
} |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
protected function consolidate_query( $data ) { |
304
|
|
|
|
305
|
|
|
if ( $data['storage_info']['type'] !== $this->queries->get_field( 'slug' ) ) { |
306
|
|
|
|
307
|
|
|
$parent_id = null; |
308
|
|
|
if ( isset( $this->query ) ) { |
309
|
|
|
$parent_id = $this->query->get_id(); |
310
|
|
|
} |
311
|
|
|
|
312
|
|
|
$this->query = new WordPoints_Hierarchy( 'sub_args' ); |
313
|
|
|
|
314
|
|
|
$this->queries->push( |
315
|
|
|
$data['storage_info']['type'] |
316
|
|
|
, array( 'query' => $this->query, 'parent_id' => $parent_id ) |
317
|
|
|
); |
318
|
|
|
|
319
|
|
|
$pushed_query = true; |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
if ( isset( $data['sub_args'] ) ) { |
323
|
|
|
$sub_args = $data['sub_args']; |
324
|
|
|
unset( $data['sub_args'] ); |
325
|
|
|
} |
326
|
|
|
|
327
|
|
|
$this->query->push( $data['slug'], $data ); |
328
|
|
|
|
329
|
|
|
if ( isset( $sub_args ) ) { |
330
|
|
|
$this->consolidate_queries( $sub_args, $data['storage_info']['type'] ); |
331
|
|
|
} |
332
|
|
|
|
333
|
|
|
$this->query->pop(); |
334
|
|
|
|
335
|
|
|
if ( ! empty( $pushed_query ) ) { |
336
|
|
|
$this->queries->pop(); |
337
|
|
|
$this->query = $this->queries->get_field( 'query' ); |
338
|
|
|
} |
339
|
|
|
} |
340
|
|
|
|
341
|
|
|
protected function execute_queries( $queries ) { |
342
|
|
|
|
343
|
|
|
/** @var WordPoints_HierarchyI $query */ |
344
|
|
|
$query = $queries['query']; |
345
|
|
|
|
346
|
|
|
if ( isset( $queries['sub_queries'] ) ) { |
347
|
|
|
foreach ( $queries['sub_queries'] as $query_data ) { |
348
|
|
|
|
349
|
|
|
$results = $this->execute_queries( $query_data ); |
350
|
|
|
|
351
|
|
|
if ( is_wp_error( $results ) ) { |
352
|
|
|
return $results; |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
if ( empty( $results ) ) { |
356
|
|
|
return array(); |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
/** @var WordPoints_HierarchyI $child_query */ |
360
|
|
|
$child_query = $query_data['query']; |
361
|
|
|
$query->go_to( $query_data['parent_id'] ); |
362
|
|
|
|
363
|
|
|
$condition = array( |
364
|
|
|
// 'field' => $child_query->get_field( 'slug' ), |
|
|
|
|
365
|
|
|
'compare' => 'in', |
366
|
|
|
'value' => wp_list_pluck( |
367
|
|
|
$results |
368
|
|
|
, $child_query->get_field( 'storage_info', 'meta', 'id_field' ) |
369
|
|
|
), |
370
|
|
|
); |
371
|
|
|
|
372
|
|
|
$query->push_to( 'conditions', $condition ); |
373
|
|
|
} |
374
|
|
|
} |
375
|
|
|
|
376
|
|
|
$query->reset(); |
377
|
|
|
$storage_type = $query->get_field( 'storage_info', 'type' ); |
378
|
|
|
|
379
|
|
|
// it is pretty stupid to wait until now to figure this out. |
380
|
|
|
$executor = $this->hooks->get_sub_app( 'retroactive_query_executors' )->get( $storage_type ); |
381
|
|
|
|
382
|
|
|
if ( ! $executor ) { |
383
|
|
|
$this->validator->add_error( |
384
|
|
|
sprintf( 'unknown storage type "%s".', $storage_type ) |
385
|
|
|
); |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
return $executor->execute( array( $query->get() ) ); |
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
protected function filter_results() { |
392
|
|
|
|
393
|
|
|
$reactor = $this->hooks->get_sub_app( 'reactors' )->get( $this->reaction->get_reactor_slug() ); |
394
|
|
|
|
395
|
|
|
if ( $reactor instanceof WordPoints_Hook_Retroactive_Query_FilterI ) { |
396
|
|
|
$reactor->filter_retroactive_query( $this ); |
397
|
|
|
} |
398
|
|
|
|
399
|
|
|
foreach ( $this->hooks->get_sub_app( 'extensions' )->get_all() as $extension ) { |
400
|
|
|
if ( $extension instanceof WordPoints_Hook_Retroactive_Query_FilterI ) { |
401
|
|
|
$extension->filter_retroactive_query( $this ); |
402
|
|
|
} |
403
|
|
|
} |
404
|
|
|
} |
405
|
|
|
|
406
|
|
|
protected function group_results() { |
407
|
|
|
|
408
|
|
|
$grouped_results = array(); |
409
|
|
|
|
410
|
|
|
foreach ( $this->results as $result ) { |
411
|
|
|
$grouped_results[ $result->target ][] = $result; |
412
|
|
|
} |
413
|
|
|
|
414
|
|
|
$this->results = $grouped_results; |
415
|
|
|
} |
416
|
|
|
|
417
|
|
|
public function add_condition( array $condition ) { |
418
|
|
|
|
419
|
|
|
$this->arg_hierarchy->push_to( 'conditions', $condition ); |
|
|
|
|
420
|
|
|
} |
421
|
|
|
|
422
|
|
|
public function select_value( $data = array() ) { |
423
|
|
|
|
424
|
|
|
$this->arg_hierarchy->set_field( 'select', $data ); |
|
|
|
|
425
|
|
|
} |
426
|
|
|
|
427
|
|
|
public function set_target( $target_arg ) { |
428
|
|
|
|
429
|
|
|
foreach ( $target_arg as $arg_slug ) { |
430
|
|
|
$this->arg_hierarchy_push( $arg_slug ); |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
// $id = $this->arg_hierarchy->get_id(); |
|
|
|
|
434
|
|
|
// |
435
|
|
|
// // If this entity has a parent relationship, we |
436
|
|
|
// if ( $this->arg_hierarchy->ascend() ) { |
437
|
|
|
// $field = $this->arg_hierarchy->get_field( 'storage_info', 'meta', 'field' ); |
438
|
|
|
// $this->arg_hierarchy->ascend(); |
439
|
|
|
// } else { |
440
|
|
|
$field = $this->arg_hierarchy->get_field( 'storage_info', 'meta', 'id_field' ); |
|
|
|
|
441
|
|
|
// } |
442
|
|
|
|
443
|
|
|
$this->select_value( array( 'field' => $field, 'as' => 'target' ) ); |
444
|
|
|
|
445
|
|
|
// $this->arg_hierarchy->go_to( $id ); |
|
|
|
|
446
|
|
|
} |
447
|
|
|
|
448
|
|
|
/** |
449
|
|
|
* |
450
|
|
|
* |
451
|
|
|
* @since 1. |
452
|
|
|
* @return WordPoints_EntityishI |
453
|
|
|
*/ |
454
|
|
|
public function get_arg() { |
455
|
|
|
return $this->arg_hierarchy->get_field( 'arg' ); |
|
|
|
|
456
|
|
|
} |
457
|
|
|
|
458
|
|
|
public function arg_hierarchy_push( $slug ) { |
459
|
|
|
|
460
|
|
|
$current_slug = $this->arg_hierarchy->get_field( 'slug' ); |
|
|
|
|
461
|
|
|
|
462
|
|
|
if ( $current_slug === $slug && $this->arg_hierarchy->is_main() ) { |
|
|
|
|
463
|
|
|
return; |
464
|
|
|
} |
465
|
|
|
|
466
|
|
|
// if ( $current_slug !== $slug ) { |
|
|
|
|
467
|
|
|
|
468
|
|
|
if ( empty( $current_slug ) ) { |
469
|
|
|
$arg = $this->entities->get( $slug ); |
470
|
|
|
} else { |
471
|
|
|
|
472
|
|
|
// If this child exists, don't overwrite it, just descend into it. |
473
|
|
|
if ( $this->arg_hierarchy->has_child( $slug ) ) { |
|
|
|
|
474
|
|
|
$this->arg_hierarchy->descend( $slug ); |
|
|
|
|
475
|
|
|
return; |
476
|
|
|
} |
477
|
|
|
|
478
|
|
|
$parent_arg = $this->arg_hierarchy->get_field( 'arg' ); |
|
|
|
|
479
|
|
|
|
480
|
|
|
if ( $parent_arg instanceof WordPoints_Entity_ParentI ) { |
|
|
|
|
481
|
|
|
$arg = $parent_arg->get_child( $slug ); |
482
|
|
|
} else { |
483
|
|
|
return; // TODO |
484
|
|
|
} |
485
|
|
|
} |
486
|
|
|
|
487
|
|
|
if ( $arg instanceof WordPoints_Entity_Array ) { |
|
|
|
|
488
|
|
|
$arg = $this->entities->get( $arg->get_entity_slug() ); |
489
|
|
|
} |
490
|
|
|
|
491
|
|
|
$data['arg'] = $arg; |
|
|
|
|
492
|
|
|
|
493
|
|
|
// TODO check if storage type is recognized? |
494
|
|
|
$data['storage_info'] = $arg->get_storage_info(); |
495
|
|
|
|
496
|
|
|
$this->arg_hierarchy->push( $slug, $data ); |
|
|
|
|
497
|
|
|
|
498
|
|
|
// } else { |
|
|
|
|
499
|
|
|
// $data = array(); |
500
|
|
|
// } |
501
|
|
|
} |
502
|
|
|
|
503
|
|
|
public function arg_hierarchy_pop() { |
504
|
|
|
$this->arg_hierarchy->pop(); |
|
|
|
|
505
|
|
|
} |
506
|
|
|
|
507
|
|
|
public function reset() { |
508
|
|
|
$this->arg_hierarchy->reset(); |
|
|
|
|
509
|
|
|
} |
510
|
|
|
} |
511
|
|
|
|
512
|
|
|
interface WordPoints_Hook_Retroactive_Query_FilterI { |
513
|
|
|
public function filter_retroactive_query( WordPoints_Hook_Retroactive_QueryI $query ); |
514
|
|
|
} |
515
|
|
|
|
516
|
|
|
interface WordPoints_Hook_Retroactive_Query_ExecutorI { |
517
|
|
|
public function execute( $query ); |
518
|
|
|
} |
519
|
|
|
|
520
|
|
|
/* |
521
|
|
|
* 1. We need to know what element is supposed to process each piece. |
522
|
|
|
* 2. We need to let the target modify the query. |
523
|
|
|
* 3. All elements must add their conditions to the query, even when the query won't |
524
|
|
|
* be able to process them. Otherwise we'll be doing a lot of unnecessary filtering. |
525
|
|
|
* |
526
|
|
|
* |
527
|
|
|
* |
528
|
|
|
* We can only do a COUNT(*) and GROUP BY when no other fields beside the target |
529
|
|
|
* need to be returned. When their are other fields added for filters that will run |
530
|
|
|
* later, we would have to perform the COUNT(*) and GROUP BY after filtering. |
531
|
|
|
* |
532
|
|
|
* But What if the target needs multiple fields but also the GROUP BY and count? |
533
|
|
|
* Should we just let it do the processing for that itself in that case? |
534
|
|
|
*/ |
535
|
|
|
|
536
|
|
|
|
537
|
|
|
|
538
|
|
|
class WordPoints_Hook_Retroactive_Query_Executor_Array |
539
|
|
|
implements WordPoints_Hook_Retroactive_Query_ExecutorI { |
540
|
|
|
|
541
|
|
|
protected $parent_data; |
542
|
|
|
|
543
|
|
|
protected $array; |
544
|
|
|
protected $results; |
545
|
|
|
|
546
|
|
|
public function execute( $query ) { |
547
|
|
|
|
548
|
|
|
foreach ( $query as $arg_data ) { |
549
|
|
|
|
550
|
|
|
$meta = $arg_data['storage_info']['meta']; |
551
|
|
|
|
552
|
|
|
if ( isset( $meta['getter'] ) ) { |
553
|
|
|
$this->array = $meta['getter'](); |
554
|
|
|
} |
555
|
|
|
|
556
|
|
|
if ( isset( $arg_data['conditions'] ) ) { |
557
|
|
|
|
558
|
|
|
foreach ( $arg_data['conditions'] as $condition ) { |
559
|
|
|
|
560
|
|
|
if ( ! isset( $condition['field'] ) ) { |
561
|
|
|
if ( $arg_data['arg'] instanceof WordPoints_Entity_Attr ) { |
|
|
|
|
562
|
|
|
$condition['field'] = $meta['field']; |
563
|
|
|
} else { |
564
|
|
|
$condition['field'] = $meta['id_field']; |
565
|
|
|
} |
566
|
|
|
} |
567
|
|
|
|
568
|
|
|
if ( ! isset( $condition['condition'] ) ) { |
569
|
|
|
$condition['condition'] = '='; |
570
|
|
|
} |
571
|
|
|
|
572
|
|
|
$filter_args = array(); |
573
|
|
|
|
574
|
|
|
switch ( $condition['condition'] ) { |
575
|
|
|
|
576
|
|
|
case '=': |
577
|
|
|
$filter_args[ $condition['field'] ] = $condition['value']; |
578
|
|
|
break; |
579
|
|
|
|
580
|
|
|
case 'in': |
581
|
|
|
// TODO |
582
|
|
|
|
583
|
|
|
default: |
584
|
|
|
return new WP_Error( 'invalid condition type' ); |
585
|
|
|
} |
586
|
|
|
|
587
|
|
|
$this->array = wp_list_filter( $this->array, $filter_args ); |
588
|
|
|
} |
589
|
|
|
} |
590
|
|
|
|
591
|
|
|
// if ( isset( $arg_data['select'] ) ) { |
|
|
|
|
592
|
|
|
// $builder->add_field( $arg_data['select'] ); |
593
|
|
|
// } |
594
|
|
|
|
595
|
|
|
if ( isset( $arg_data['sub_args'] ) ) { |
596
|
|
|
$this->parent_data = $arg_data; |
597
|
|
|
$this->array = $this->execute( $arg_data['sub_args'] ); |
598
|
|
|
} |
599
|
|
|
|
600
|
|
|
$this->results = $this->array; |
601
|
|
|
} |
602
|
|
|
|
603
|
|
|
return $this->results; |
604
|
|
|
} |
605
|
|
|
} |
606
|
|
|
|
607
|
|
|
//wordpoints_hooks()->retroactive_query_executors->register( 'array', 'WordPoints_Hook_Retroactive_Query_Executor_Array' ); |
|
|
|
|
608
|
|
|
|
609
|
|
|
class WordPoints_Hook_Retroactive_Query_Executor_MySQL |
610
|
|
|
implements WordPoints_Hook_Retroactive_Query_ExecutorI { |
611
|
|
|
|
612
|
|
|
/** |
613
|
|
|
* |
614
|
|
|
* |
615
|
|
|
* @since 1. |
616
|
|
|
* |
617
|
|
|
* @var WordPoints_Query_BuilderI |
618
|
|
|
*/ |
619
|
|
|
protected $builder; |
620
|
|
|
protected $arg_data; |
621
|
|
|
protected $parent_data; |
622
|
|
|
protected $grandparent_data; |
623
|
|
|
|
624
|
|
|
protected $entered_join; |
625
|
|
|
|
626
|
|
|
public function execute( $query ) { |
627
|
|
|
// WE should be getting a hierarchy object here. |
628
|
|
|
// This will let us loop over things easier. |
629
|
|
|
// We'll also need to be marking the non-usable parts of the query. |
630
|
|
|
// We'll need to test that as well. |
631
|
|
|
|
632
|
|
|
global $wpdb; |
633
|
|
|
|
634
|
|
|
$this->builder = new WordPoints_Query_Builder_DB_MySQL(); |
635
|
|
|
|
636
|
|
|
$this->build_query( $query ); |
637
|
|
|
|
638
|
|
|
$sql = $this->builder->get_query(); |
639
|
|
|
|
640
|
|
|
if ( is_wp_error( $sql ) ) { |
641
|
|
|
return $sql; |
642
|
|
|
} |
643
|
|
|
|
644
|
|
|
return $wpdb->get_results( $sql ); |
645
|
|
|
} |
646
|
|
|
|
647
|
|
|
protected function build_query( $args ) { |
648
|
|
|
|
649
|
|
|
foreach ( $args as $arg_data ) { |
650
|
|
|
|
651
|
|
|
$this->arg_data = $arg_data; |
652
|
|
|
|
653
|
|
|
if ( isset( $arg_data['storage_info']['meta']['table_name'] ) ) { |
654
|
|
|
$this->build_table_schema( $arg_data['storage_info']['meta'] ); |
655
|
|
|
} |
656
|
|
|
|
657
|
|
|
if ( isset( $arg_data['conditions'] ) ) { |
658
|
|
|
$this->build_conditions( $arg_data['conditions'] ); |
659
|
|
|
} |
660
|
|
|
|
661
|
|
|
if ( isset( $arg_data['select'] ) ) { |
662
|
|
|
$this->builder->add_field( $arg_data['select'] ); |
663
|
|
|
} |
664
|
|
|
|
665
|
|
|
if ( isset( $arg_data['sub_args'] ) ) { |
666
|
|
|
|
667
|
|
|
$this->grandparent_data = $this->parent_data; |
668
|
|
|
$this->parent_data = $arg_data; |
669
|
|
|
|
670
|
|
|
$this->build_query( $arg_data['sub_args'] ); |
671
|
|
|
|
672
|
|
|
$this->parent_data = $this->grandparent_data; |
673
|
|
|
} |
674
|
|
|
|
675
|
|
|
if ( isset( $this->entered_join ) ) { |
676
|
|
|
$this->builder->exit_join(); |
677
|
|
|
$this->entered_join = null; |
678
|
|
|
} |
679
|
|
|
} |
680
|
|
|
} |
681
|
|
|
|
682
|
|
|
protected function build_table_schema( $db ) { |
683
|
|
|
|
684
|
|
|
if ( $this->builder->get_table() ) { |
685
|
|
|
|
686
|
|
|
if ( $this->parent_data['arg'] instanceof WordPoints_Entity_Relationship ) { |
|
|
|
|
687
|
|
|
$primary_field = $this->parent_data['storage_info']['meta']['field']; |
688
|
|
|
$join_field = $db['id_field']; |
689
|
|
|
//$primary_field = $this->arg_data['arg']->get_secondary_field(); |
|
|
|
|
690
|
|
|
} elseif ( $this->arg_data['arg'] instanceof WordPoints_Entity_Relationship ) { |
|
|
|
|
691
|
|
|
$join_field = $db['join_field']; |
692
|
|
|
$primary_field = $this->parent_data['storage_info']['meta']['id_field']; |
693
|
|
|
} else { |
694
|
|
|
throw new WordPoints_Query_Builder_Exception( 'Houston, we have a problem.' ); |
695
|
|
|
} |
696
|
|
|
|
697
|
|
|
if ( is_array( $primary_field ) && isset( $primary_field['table_name'] ) ) { |
698
|
|
|
$this->builder->enter_join( $primary_field ); |
699
|
|
|
$primary_field = $primary_field['on']['join_field']; |
700
|
|
|
} |
701
|
|
|
|
702
|
|
|
$join = array( |
703
|
|
|
'table_name' => $db['table_name'], |
704
|
|
|
'on' => array( |
705
|
|
|
'join_field' => $join_field, |
706
|
|
|
'primary_field' => $primary_field, |
707
|
|
|
), |
708
|
|
|
); |
709
|
|
|
|
710
|
|
|
if ( isset( $db['join_where'] ) ) { |
711
|
|
|
$join['where'] = $db['join_where']; |
712
|
|
|
} |
713
|
|
|
|
714
|
|
|
$this->builder->enter_join( $join ); |
715
|
|
|
|
716
|
|
|
$this->entered_join = true; |
717
|
|
|
|
718
|
|
|
} else { |
719
|
|
|
$this->builder->set_table( $db['table_name'] ); |
720
|
|
|
$this->builder->add_field( $db['id_field'] ); |
721
|
|
|
} |
722
|
|
|
} |
723
|
|
|
|
724
|
|
|
protected function build_conditions( $conditions ) { |
725
|
|
|
|
726
|
|
|
// Join conditions should be pushed to the end. |
727
|
|
|
$join_conditions = array(); |
728
|
|
|
|
729
|
|
|
foreach ( $conditions as $condition ) { |
730
|
|
|
|
731
|
|
|
// THis needs to be the identifier field for the type of arg that this |
732
|
|
|
// field represents. |
733
|
|
|
// FOr an entity, that would be the id_field. |
734
|
|
|
// However, for a relationship it could be something else. |
735
|
|
|
// Ultimately, this will have to be left up to the arg object to |
736
|
|
|
// decide. |
737
|
|
|
if ( ! isset( $condition['field'] ) ) { |
738
|
|
|
if ( $this->arg_data['arg'] instanceof WordPoints_Entity_Relationship ) { |
|
|
|
|
739
|
|
|
// $condition['field'] = $this->arg_data['arg']->get_secondary_field(); |
|
|
|
|
740
|
|
|
$condition['field'] = $this->arg_data['storage_info']['meta']['field']; |
741
|
|
|
|
742
|
|
|
if ( is_array( $condition['field'] && isset( $condition['field']['table_name'] ) ) ) { |
743
|
|
|
$join_conditions[] = $condition; |
744
|
|
|
continue; |
745
|
|
|
} |
746
|
|
|
} elseif ( $this->arg_data['arg'] instanceof WordPoints_Entity_Attr ) { |
|
|
|
|
747
|
|
|
$condition['field'] = $this->arg_data['arg']->get_field(); |
748
|
|
|
} else { |
749
|
|
|
var_dump($this->arg_data['arg']);exit; |
|
|
|
|
750
|
|
|
} |
751
|
|
|
} |
752
|
|
|
|
753
|
|
|
$this->builder->where( $condition ); |
754
|
|
|
} |
755
|
|
|
|
756
|
|
|
$join_count = count( $join_conditions ); |
757
|
|
|
$i = 0; |
758
|
|
|
|
759
|
|
|
foreach ( $join_conditions as $condition ) { |
760
|
|
|
|
761
|
|
|
$i++; |
762
|
|
|
|
763
|
|
|
$this->builder->enter_join( $condition['field'] ); |
764
|
|
|
|
765
|
|
|
$condition['field'] = $condition['field']['on']['primary_field']; |
766
|
|
|
|
767
|
|
|
$this->builder->where( $condition ); |
768
|
|
|
|
769
|
|
|
$this->builder->exit_join(); |
770
|
|
|
|
771
|
|
|
// If there are more join conditions, we need to leave a fresh, trailing |
772
|
|
|
// join for the next one to join to. |
773
|
|
|
if ( $i < $join_count ) { |
774
|
|
|
|
775
|
|
|
// There is a current join, but it is already being used, so we |
776
|
|
|
// need to exit it. |
777
|
|
|
$this->builder->exit_join(); |
778
|
|
|
|
779
|
|
|
// Then we just build the schema again like before. |
780
|
|
|
$this->build_table_schema( |
781
|
|
|
$this->arg_data['storage_info']['meta'] |
782
|
|
|
); |
783
|
|
|
} |
784
|
|
|
} |
785
|
|
|
} |
786
|
|
|
} |
787
|
|
|
|
788
|
|
|
|
789
|
|
|
//wordpoints_hooks()->retroactive_query_executors->register( 'db', 'WordPoints_Hook_Retroactive_Query_Executor_MySQL' ); |
|
|
|
|
790
|
|
|
|
791
|
|
|
|
792
|
|
|
// EOF |
793
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.