1
|
|
|
<?php |
2
|
|
|
namespace EventEspresso\core\libraries\rest_api\controllers\model; |
3
|
|
|
|
4
|
|
|
use EventEspresso\core\libraries\rest_api\Capabilities; |
5
|
|
|
use EventEspresso\core\libraries\rest_api\Calculated_Model_Fields; |
6
|
|
|
use EventEspresso\core\libraries\rest_api\Rest_Exception; |
7
|
|
|
use EventEspresso\core\libraries\rest_api\Model_Data_Translator; |
8
|
|
|
|
9
|
|
|
if ( !defined( 'EVENT_ESPRESSO_VERSION' ) ) { |
10
|
|
|
exit( 'No direct script access allowed' ); |
11
|
|
|
} |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* |
15
|
|
|
* Read controller for models |
16
|
|
|
* |
17
|
|
|
* Handles requests relating to GET-ting model information |
18
|
|
|
* |
19
|
|
|
* @package Event Espresso |
20
|
|
|
* @subpackage |
21
|
|
|
* @author Mike Nelson |
22
|
|
|
* |
23
|
|
|
*/ |
24
|
|
|
class Read extends Base { |
25
|
|
|
|
26
|
|
|
|
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* |
30
|
|
|
* @var Calculated_Model_Fields |
31
|
|
|
*/ |
32
|
|
|
protected $_fields_calculator; |
33
|
|
|
|
34
|
|
|
|
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* Read constructor. |
38
|
|
|
*/ |
39
|
|
|
public function __construct() { |
40
|
|
|
parent::__construct(); |
41
|
|
|
\EE_Registry::instance()->load_helper( 'Inflector' ); |
42
|
|
|
$this->_fields_calculator = new Calculated_Model_Fields(); |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Handles requests to get all (or a filtered subset) of entities for a particular model |
47
|
|
|
* @param \WP_REST_Request $request |
48
|
|
|
* @return \WP_REST_Response|\WP_Error |
49
|
|
|
*/ |
50
|
|
View Code Duplication |
public static function handle_request_get_all( \WP_REST_Request $request) { |
|
|
|
|
51
|
|
|
$controller = new Read(); |
52
|
|
|
try{ |
53
|
|
|
$matches = $controller->parse_route( |
54
|
|
|
$request->get_route(), |
55
|
|
|
'~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)~', |
56
|
|
|
array( 'version', 'model' ) |
57
|
|
|
); |
58
|
|
|
$controller->set_requested_version( $matches[ 'version' ] ); |
59
|
|
|
$model_name_singular = \EEH_Inflector::singularize_and_upper( $matches[ 'model' ] ); |
60
|
|
|
if ( ! $controller->get_model_version_info()->is_model_name_in_this_version( $model_name_singular ) ) { |
61
|
|
|
return $controller->send_response( |
62
|
|
|
new \WP_Error( |
63
|
|
|
'endpoint_parsing_error', |
64
|
|
|
sprintf( |
65
|
|
|
__( 'There is no model for endpoint %s. Please contact event espresso support', 'event_espresso' ), |
66
|
|
|
$model_name_singular |
67
|
|
|
) |
68
|
|
|
) |
69
|
|
|
); |
70
|
|
|
} |
71
|
|
|
return $controller->send_response( |
72
|
|
|
$controller->get_entities_from_model( |
73
|
|
|
$controller->get_model_version_info()->load_model( $model_name_singular ), |
|
|
|
|
74
|
|
|
$request |
75
|
|
|
) |
76
|
|
|
); |
77
|
|
|
} catch( \Exception $e ) { |
78
|
|
|
return $controller->send_response( $e ); |
79
|
|
|
} |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Gets a single entity related to the model indicated in the path and its id |
84
|
|
|
* |
85
|
|
|
* @param \WP_REST_Request $request |
86
|
|
|
* @return \WP_REST_Response|\WP_Error |
87
|
|
|
*/ |
88
|
|
View Code Duplication |
public static function handle_request_get_one( \WP_REST_Request $request ) { |
|
|
|
|
89
|
|
|
$controller = new Read(); |
90
|
|
|
try{ |
91
|
|
|
$matches = $controller->parse_route( |
92
|
|
|
$request->get_route(), |
93
|
|
|
'~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)/(.*)~', |
94
|
|
|
array( 'version', 'model', 'id' ) ); |
95
|
|
|
$controller->set_requested_version( $matches[ 'version' ] ); |
96
|
|
|
$model_name_singular = \EEH_Inflector::singularize_and_upper( $matches[ 'model' ] ); |
97
|
|
|
if ( ! $controller->get_model_version_info()->is_model_name_in_this_version( $model_name_singular ) ) { |
98
|
|
|
return $controller->send_response( |
99
|
|
|
new \WP_Error( |
100
|
|
|
'endpoint_parsing_error', |
101
|
|
|
sprintf( |
102
|
|
|
__( 'There is no model for endpoint %s. Please contact event espresso support', 'event_espresso' ), |
103
|
|
|
$model_name_singular |
104
|
|
|
) |
105
|
|
|
) |
106
|
|
|
); |
107
|
|
|
} |
108
|
|
|
return $controller->send_response( |
109
|
|
|
$controller->get_entity_from_model( |
110
|
|
|
$controller->get_model_version_info()->load_model( $model_name_singular ), |
|
|
|
|
111
|
|
|
$request |
112
|
|
|
) |
113
|
|
|
); |
114
|
|
|
} catch( \Exception $e ) { |
115
|
|
|
return $controller->send_response( $e ); |
116
|
|
|
} |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* |
121
|
|
|
* Gets all the related entities (or if its a belongs-to relation just the one) |
122
|
|
|
* to the item with the given id |
123
|
|
|
* |
124
|
|
|
* @param \WP_REST_Request $request |
125
|
|
|
* @return \WP_REST_Response|\WP_Error |
126
|
|
|
*/ |
127
|
|
|
public static function handle_request_get_related( \WP_REST_Request $request ) { |
128
|
|
|
$controller = new Read(); |
129
|
|
|
try{ |
130
|
|
|
$matches = $controller->parse_route( |
131
|
|
|
$request->get_route(), |
132
|
|
|
'~' . \EED_Core_Rest_Api::ee_api_namespace_for_regex . '(.*)/(.*)/(.*)~', |
133
|
|
|
array( 'version', 'model', 'id', 'related_model' ) |
134
|
|
|
); |
135
|
|
|
$controller->set_requested_version( $matches[ 'version' ] ); |
136
|
|
|
$main_model_name_singular = \EEH_Inflector::singularize_and_upper( $matches[ 'model' ] ); |
137
|
|
|
if ( ! $controller->get_model_version_info()->is_model_name_in_this_version( $main_model_name_singular ) ) { |
138
|
|
|
return $controller->send_response( |
139
|
|
|
new \WP_Error( |
140
|
|
|
'endpoint_parsing_error', |
141
|
|
|
sprintf( |
142
|
|
|
__( 'There is no model for endpoint %s. Please contact event espresso support', 'event_espresso' ), |
143
|
|
|
$main_model_name_singular |
144
|
|
|
) |
145
|
|
|
) |
146
|
|
|
); |
147
|
|
|
} |
148
|
|
|
$main_model = $controller->get_model_version_info()->load_model( $main_model_name_singular ); |
149
|
|
|
//assume the related model name is plural and try to find the model's name |
150
|
|
|
$related_model_name_singular = \EEH_Inflector::singularize_and_upper( $matches[ 'related_model' ] ); |
151
|
|
|
if ( ! $controller->get_model_version_info()->is_model_name_in_this_version( $related_model_name_singular ) ) { |
152
|
|
|
//so the word didn't singularize well. Maybe that's just because it's a singular word? |
153
|
|
|
$related_model_name_singular = \EEH_Inflector::humanize( $matches[ 'related_model' ] ); |
154
|
|
|
} |
155
|
|
|
if ( ! $controller->get_model_version_info()->is_model_name_in_this_version( $related_model_name_singular ) ) { |
156
|
|
|
return $controller->send_response( |
157
|
|
|
new \WP_Error( |
158
|
|
|
'endpoint_parsing_error', |
159
|
|
|
sprintf( |
160
|
|
|
__( 'There is no model for endpoint %s. Please contact event espresso support', 'event_espresso' ), |
161
|
|
|
$related_model_name_singular |
162
|
|
|
) |
163
|
|
|
) |
164
|
|
|
); |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
return $controller->send_response( |
168
|
|
|
$controller->get_entities_from_relation( |
169
|
|
|
$request->get_param( 'id' ), |
170
|
|
|
$main_model->related_settings_for( $related_model_name_singular ) , |
|
|
|
|
171
|
|
|
$request |
172
|
|
|
) |
173
|
|
|
); |
174
|
|
|
} catch( \Exception $e ) { |
175
|
|
|
return $controller->send_response( $e ); |
176
|
|
|
} |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
|
180
|
|
|
|
181
|
|
|
/** |
182
|
|
|
* Gets a collection for the given model and filters |
183
|
|
|
* |
184
|
|
|
* @param \EEM_Base $model |
185
|
|
|
* @param \WP_REST_Request $request |
186
|
|
|
* @return array |
187
|
|
|
*/ |
188
|
|
|
public function get_entities_from_model( $model, $request) { |
189
|
|
|
$query_params = $this->create_model_query_params( $model, $request->get_params() ); |
190
|
|
|
if( ! Capabilities::current_user_has_partial_access_to( $model, $query_params[ 'caps' ] ) ) { |
191
|
|
|
$model_name_plural = \EEH_Inflector::pluralize_and_lower( $model->get_this_model_name() ); |
192
|
|
|
return new \WP_Error( |
193
|
|
|
sprintf( 'rest_%s_cannot_list', $model_name_plural ), |
194
|
|
|
sprintf( |
195
|
|
|
__( 'Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso' ), |
196
|
|
|
$model_name_plural, |
197
|
|
|
Capabilities::get_missing_permissions_string( $model, $query_params[ 'caps' ] ) |
198
|
|
|
), |
199
|
|
|
array( 'status' => 403 ) |
200
|
|
|
); |
201
|
|
|
} |
202
|
|
|
if( ! $request->get_header( 'no_rest_headers' ) ) { |
203
|
|
|
$this->_set_headers_from_query_params( $model, $query_params ); |
204
|
|
|
} |
205
|
|
|
/** @type array $results */ |
206
|
|
|
$results = $model->get_all_wpdb_results( $query_params ); |
207
|
|
|
$nice_results = array( ); |
208
|
|
|
foreach ( $results as $result ) { |
209
|
|
|
$nice_results[ ] = $this->create_entity_from_wpdb_result( |
210
|
|
|
$model, |
211
|
|
|
$result, |
212
|
|
|
$request |
213
|
|
|
); |
214
|
|
|
} |
215
|
|
|
return $nice_results; |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
/** |
219
|
|
|
* Gets the collection for given relation object |
220
|
|
|
* |
221
|
|
|
* The same as Read::get_entities_from_model(), except if the relation |
222
|
|
|
* is a HABTM relation, in which case it merges any non-foreign-key fields from |
223
|
|
|
* the join-model-object into the results |
224
|
|
|
* |
225
|
|
|
* @param string $id the ID of the thing we are fetching related stuff from |
226
|
|
|
* @param \EE_Model_Relation_Base $relation |
227
|
|
|
* @param \WP_REST_Request $request |
228
|
|
|
* @return array |
229
|
|
|
*/ |
230
|
|
|
public function get_entities_from_relation( $id, $relation, $request ) { |
231
|
|
|
$context = $this->validate_context( $request->get_param( 'caps' )); |
232
|
|
|
$model = $relation->get_this_model(); |
233
|
|
|
$related_model = $relation->get_other_model(); |
234
|
|
|
//check if they can access the 1st model object |
235
|
|
|
$query_params = array( array( $model->primary_key_name() => $id ),'limit' => 1 ); |
|
|
|
|
236
|
|
|
if( $model instanceof \EEM_Soft_Delete_Base ){ |
237
|
|
|
$query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params); |
238
|
|
|
} |
239
|
|
|
$restricted_query_params = $query_params; |
240
|
|
|
$restricted_query_params[ 'caps' ] = $context; |
241
|
|
|
$this->_set_debug_info( 'main model query params', $restricted_query_params ); |
242
|
|
|
$this->_set_debug_info( 'missing caps', Capabilities::get_missing_permissions_string( $related_model, $context ) ); |
|
|
|
|
243
|
|
|
|
244
|
|
|
if( |
245
|
|
|
! ( |
246
|
|
|
Capabilities::current_user_has_partial_access_to( $related_model, $context ) |
|
|
|
|
247
|
|
|
&& $model->exists( $restricted_query_params ) |
|
|
|
|
248
|
|
|
) |
249
|
|
|
){ |
250
|
|
|
if( $relation instanceof \EE_Belongs_To_Relation ) { |
251
|
|
|
$related_model_name_maybe_plural = strtolower( $related_model->get_this_model_name() ); |
|
|
|
|
252
|
|
|
}else{ |
253
|
|
|
$related_model_name_maybe_plural = \EEH_Inflector::pluralize_and_lower( $related_model->get_this_model_name() ); |
|
|
|
|
254
|
|
|
} |
255
|
|
|
return new \WP_Error( |
|
|
|
|
256
|
|
|
sprintf( 'rest_%s_cannot_list', $related_model_name_maybe_plural ), |
257
|
|
|
sprintf( |
258
|
|
|
__( 'Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s', 'event_espresso' ), |
259
|
|
|
$related_model_name_maybe_plural, |
260
|
|
|
$relation->get_this_model()->get_this_model_name(), |
|
|
|
|
261
|
|
|
implode( |
262
|
|
|
',', |
263
|
|
|
array_keys( |
264
|
|
|
Capabilities::get_missing_permissions( $related_model, $context ) |
|
|
|
|
265
|
|
|
) |
266
|
|
|
) |
267
|
|
|
), |
268
|
|
|
array( 'status' => 403 ) |
269
|
|
|
); |
270
|
|
|
} |
271
|
|
|
$query_params = $this->create_model_query_params( $relation->get_other_model(), $request->get_params() ); |
|
|
|
|
272
|
|
|
$query_params[0][ $relation->get_this_model()->get_this_model_name() . '.' . $relation->get_this_model()->primary_key_name() ] = $id; |
|
|
|
|
273
|
|
|
$query_params[ 'default_where_conditions' ] = 'none'; |
274
|
|
|
$query_params[ 'caps' ] = $context; |
275
|
|
|
if( ! $request->get_header( 'no_rest_headers' ) ) { |
276
|
|
|
$this->_set_headers_from_query_params( $relation->get_other_model(), $query_params ); |
|
|
|
|
277
|
|
|
} |
278
|
|
|
/** @type array $results */ |
279
|
|
|
$results = $relation->get_other_model()->get_all_wpdb_results( $query_params ); |
|
|
|
|
280
|
|
|
$nice_results = array(); |
281
|
|
|
foreach( $results as $result ) { |
282
|
|
|
$nice_result = $this->create_entity_from_wpdb_result( |
283
|
|
|
$relation->get_other_model(), |
|
|
|
|
284
|
|
|
$result, |
285
|
|
|
$request |
286
|
|
|
); |
287
|
|
|
if( $relation instanceof \EE_HABTM_Relation ) { |
288
|
|
|
//put the unusual stuff (properties from the HABTM relation) first, and make sure |
289
|
|
|
//if there are conflicts we prefer the properties from the main model |
290
|
|
|
$join_model_result = $this->create_entity_from_wpdb_result( |
291
|
|
|
$relation->get_join_model(), |
|
|
|
|
292
|
|
|
$result, |
293
|
|
|
$request |
294
|
|
|
); |
295
|
|
|
$joined_result = array_merge( $nice_result, $join_model_result ); |
296
|
|
|
//but keep the meta stuff from the main model |
297
|
|
|
if( isset( $nice_result['meta'] ) ){ |
298
|
|
|
$joined_result['meta'] = $nice_result['meta']; |
299
|
|
|
} |
300
|
|
|
$nice_result = $joined_result; |
301
|
|
|
} |
302
|
|
|
$nice_results[] = $nice_result; |
303
|
|
|
} |
304
|
|
|
if( $relation instanceof \EE_Belongs_To_Relation ){ |
305
|
|
|
return array_shift( $nice_results ); |
306
|
|
|
}else{ |
307
|
|
|
return $nice_results; |
308
|
|
|
} |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
/** |
312
|
|
|
* Sets the headers that are based on the model and query params, |
313
|
|
|
* like the total records. This should only be called on the original request |
314
|
|
|
* from the client, not on subsequent internal |
315
|
|
|
* @param \EEM_Base $model |
316
|
|
|
* @param array $query_params |
317
|
|
|
* @return void |
318
|
|
|
*/ |
319
|
|
|
protected function _set_headers_from_query_params( $model, $query_params ) { |
320
|
|
|
$this->_set_debug_info( 'model query params', $query_params ); |
321
|
|
|
$this->_set_debug_info( 'missing caps', Capabilities::get_missing_permissions_string( $model, $query_params[ 'caps' ] ) ); |
322
|
|
|
//normally the limit to a 2-part array, where the 2nd item is the limit |
323
|
|
|
if( ! isset( $query_params[ 'limit' ] ) ) { |
324
|
|
|
$query_params[ 'limit' ] = \EED_Core_Rest_Api::get_default_query_limit(); |
325
|
|
|
} |
326
|
|
|
if( is_array( $query_params[ 'limit' ] ) ) { |
327
|
|
|
$limit_parts = $query_params[ 'limit' ]; |
328
|
|
|
} else { |
329
|
|
|
$limit_parts = explode(',', $query_params[ 'limit' ] ); |
330
|
|
|
if( count( $limit_parts ) == 1 ){ |
331
|
|
|
$limit_parts = array(0, $limit_parts[ 0 ] ); |
332
|
|
|
} |
333
|
|
|
} |
334
|
|
|
//remove the group by and having parts of the query, as those will |
335
|
|
|
//make the sql query return an array of values, instead of just a single value |
336
|
|
|
unset( $query_params[ 'group_by' ], $query_params[ 'having' ], $query_params[ 'limit' ] ); |
337
|
|
|
$count = $model->count( $query_params, null, true ); |
338
|
|
|
|
339
|
|
|
$pages = $count / $limit_parts[ 1 ]; |
340
|
|
|
$this->_set_response_header( 'Total', $count, false ); |
341
|
|
|
$this->_set_response_header( 'PageSize', $limit_parts[ 1 ], false ); |
342
|
|
|
$this->_set_response_header( 'TotalPages', ceil( $pages ), false ); |
343
|
|
|
} |
344
|
|
|
|
345
|
|
|
|
346
|
|
|
|
347
|
|
|
/** |
348
|
|
|
* Changes database results into REST API entities |
349
|
|
|
* @param \EEM_Base $model |
350
|
|
|
* @param array $db_row like results from $wpdb->get_results() |
351
|
|
|
* @param \WP_REST_Request $rest_request |
352
|
|
|
* @param string $deprecated no longer used |
353
|
|
|
* @return array ready for being converted into json for sending to client |
354
|
|
|
*/ |
355
|
|
|
public function create_entity_from_wpdb_result( $model, $db_row, $rest_request, $deprecated = null ) { |
356
|
|
|
if( ! $rest_request instanceof \WP_REST_Request ) { |
|
|
|
|
357
|
|
|
//ok so this was called in the old style, where the 3rd arg was |
358
|
|
|
//$include, and the 4th arg was $context |
359
|
|
|
//now setup the request just to avoid fatal errors, although we won't be able |
360
|
|
|
//to truly make use of it because it's kinda devoid of info |
361
|
|
|
$rest_request = new \WP_REST_Request(); |
362
|
|
|
$rest_request->set_param( 'include', $rest_request ); |
363
|
|
|
$rest_request->set_param( 'caps', $deprecated ); |
364
|
|
|
} |
365
|
|
|
if( $rest_request->get_param( 'caps' ) == null ) { |
366
|
|
|
$rest_request->set_param( 'caps', \EEM_Base::caps_read ); |
367
|
|
|
} |
368
|
|
|
$entity_array = $this->_create_bare_entity_from_wpdb_results( $model, $db_row ); |
369
|
|
|
$entity_array = $this->_add_extra_fields( $model, $db_row, $entity_array ); |
370
|
|
|
$entity_array[ '_links' ] = $this->_get_entity_links( $model, $db_row, $entity_array ); |
371
|
|
|
$entity_array[ '_calculated_fields'] = $this->_get_entity_calculations( $model, $db_row, $rest_request ); |
372
|
|
|
$entity_array = $this->_include_requested_models( $model, $rest_request, $entity_array ); |
373
|
|
|
$entity_array = apply_filters( |
374
|
|
|
'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal', |
375
|
|
|
$entity_array, |
376
|
|
|
$model, |
377
|
|
|
$rest_request->get_param( 'caps' ), |
378
|
|
|
$rest_request, |
379
|
|
|
$this |
380
|
|
|
); |
381
|
|
|
$result_without_inaccessible_fields = Capabilities::filter_out_inaccessible_entity_fields( |
382
|
|
|
$entity_array, |
383
|
|
|
$model, |
384
|
|
|
$rest_request->get_param( 'caps' ), |
385
|
|
|
$this->get_model_version_info() |
386
|
|
|
); |
387
|
|
|
$this->_set_debug_info( |
388
|
|
|
'inaccessible fields', |
389
|
|
|
array_keys( array_diff_key( $entity_array, $result_without_inaccessible_fields ) ) |
390
|
|
|
); |
391
|
|
|
return apply_filters( |
392
|
|
|
'FHEE__Read__create_entity_from_wpdb_results__entity_return', |
393
|
|
|
$result_without_inaccessible_fields, |
394
|
|
|
$model, |
395
|
|
|
$rest_request->get_param( 'caps' ) |
396
|
|
|
); |
397
|
|
|
} |
398
|
|
|
|
399
|
|
|
/** |
400
|
|
|
* Creates a REST entity array (JSON object we're going to return in the response, but |
401
|
|
|
* for now still a PHP array, but soon enough we'll call json_encode on it, don't worry), |
402
|
|
|
* from $wpdb->get_row( $sql, ARRAY_A) |
403
|
|
|
* @param \EEM_Base $model |
404
|
|
|
* @param array $db_row |
405
|
|
|
* @return array entity mostly ready for converting to JSON and sending in the response |
406
|
|
|
*/ |
407
|
|
|
protected function _create_bare_entity_from_wpdb_results( \EEM_Base $model, $db_row ) { |
408
|
|
|
$result = $model->deduce_fields_n_values_from_cols_n_values( $db_row ); |
409
|
|
|
$result = array_intersect_key( $result, $this->get_model_version_info()->fields_on_model_in_this_version( $model ) ); |
410
|
|
|
foreach( $result as $field_name => $raw_field_value ) { |
411
|
|
|
$field_obj = $model->field_settings_for($field_name); |
412
|
|
|
$field_value = $field_obj->prepare_for_set_from_db( $raw_field_value ); |
413
|
|
|
if( $this->is_subclass_of_one( $field_obj, $this->get_model_version_info()->fields_ignored() ) ){ |
414
|
|
|
unset( $result[ $field_name ] ); |
415
|
|
|
}elseif( |
416
|
|
|
$this->is_subclass_of_one( $field_obj, $this->get_model_version_info()->fields_that_have_rendered_format() ) |
417
|
|
|
){ |
418
|
|
|
$result[ $field_name ] = array( |
419
|
|
|
'raw' => $field_obj->prepare_for_get( $field_value ), |
420
|
|
|
'rendered' => $field_obj->prepare_for_pretty_echoing( $field_value ) |
421
|
|
|
); |
422
|
|
|
}elseif( |
423
|
|
|
$this->is_subclass_of_one( $field_obj, $this->get_model_version_info()->fields_that_have_pretty_format() ) |
424
|
|
|
){ |
425
|
|
|
$result[ $field_name ] = array( |
426
|
|
|
'raw' => $field_obj->prepare_for_get( $field_value ), |
427
|
|
|
'pretty' => $field_obj->prepare_for_pretty_echoing( $field_value ) |
428
|
|
|
); |
429
|
|
|
} elseif ( $field_obj instanceof \EE_Datetime_Field ) { |
430
|
|
|
$result[ $field_name ] = Model_Data_Translator::prepare_field_value_for_json( |
431
|
|
|
$field_obj, |
432
|
|
|
$field_value, |
433
|
|
|
$this->get_model_version_info()->requested_version() |
434
|
|
|
); |
435
|
|
|
} else { |
436
|
|
|
$result[ $field_name ] = Model_Data_Translator::prepare_field_value_for_json( |
437
|
|
|
$field_obj, |
438
|
|
|
$field_obj->prepare_for_get( $field_value ), |
439
|
|
|
$this->get_model_version_info()->requested_version() |
440
|
|
|
); |
441
|
|
|
} |
442
|
|
|
} |
443
|
|
|
return $result; |
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
/** |
447
|
|
|
* Adds a few extra fields to the entity response |
448
|
|
|
* @param \EEM_Base $model |
449
|
|
|
* @param array $db_row |
450
|
|
|
* @param array $entity_array |
451
|
|
|
* @return array modified entity |
452
|
|
|
*/ |
453
|
|
|
protected function _add_extra_fields( \EEM_Base $model, $db_row, $entity_array ) { |
454
|
|
|
if( $model instanceof \EEM_CPT_Base ) { |
455
|
|
|
$entity_array[ 'link' ] = get_permalink( $db_row[ $model->get_primary_key_field()->get_qualified_column() ] ); |
456
|
|
|
} |
457
|
|
|
return $entity_array; |
458
|
|
|
} |
459
|
|
|
|
460
|
|
|
/** |
461
|
|
|
* Gets links we want to add to the response |
462
|
|
|
* |
463
|
|
|
*@global \WP_REST_Server $wp_rest_server |
464
|
|
|
* @param \EEM_Base $model |
465
|
|
|
* @param array $db_row |
466
|
|
|
* @param array $entity_array |
467
|
|
|
* @return array the _links item in the entity |
468
|
|
|
*/ |
469
|
|
|
protected function _get_entity_links( $model, $db_row, $entity_array ) { |
470
|
|
|
//add basic links |
471
|
|
|
$links = array( |
472
|
|
|
'self' => array( |
473
|
|
|
array( |
474
|
|
|
'href' => $this->get_versioned_link_to( |
475
|
|
|
\EEH_Inflector::pluralize_and_lower( $model->get_this_model_name() ) . '/' . $entity_array[ $model->primary_key_name() ] |
476
|
|
|
) |
477
|
|
|
) |
478
|
|
|
), |
479
|
|
|
'collection' => array( |
480
|
|
|
array( |
481
|
|
|
'href' => $this->get_versioned_link_to( |
482
|
|
|
\EEH_Inflector::pluralize_and_lower( $model->get_this_model_name() ) |
483
|
|
|
) |
484
|
|
|
) |
485
|
|
|
), |
486
|
|
|
); |
487
|
|
|
|
488
|
|
|
//add link to the wp core endpoint, if wp api is active |
489
|
|
|
global $wp_rest_server; |
490
|
|
|
if( $model instanceof \EEM_CPT_Base && |
491
|
|
|
$wp_rest_server instanceof \WP_REST_Server && |
|
|
|
|
492
|
|
|
$wp_rest_server->get_route_options( '/wp/v2/posts' ) ) { |
493
|
|
|
$links[ \EED_Core_Rest_Api::ee_api_link_namespace . 'self_wp_post' ] = array( |
494
|
|
|
array( |
495
|
|
|
'href' => rest_url( '/wp/v2/posts/' . $db_row[ $model->get_primary_key_field()->get_qualified_column() ] ), |
496
|
|
|
'single' => true |
497
|
|
|
) |
498
|
|
|
); |
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
//add links to related models |
502
|
|
|
foreach( $this->get_model_version_info()->relation_settings( $model ) as $relation_name => $relation_obj ) { |
503
|
|
|
$related_model_part = Read::get_related_entity_name( $relation_name, $relation_obj ); |
504
|
|
|
$links[ \EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part ] = array( |
505
|
|
|
array( |
506
|
|
|
'href' => $this->get_versioned_link_to( |
507
|
|
|
\EEH_Inflector::pluralize_and_lower( $model->get_this_model_name() ) . '/' . $entity_array[ $model->primary_key_name() ] . '/' . $related_model_part |
508
|
|
|
), |
509
|
|
|
'single' => $relation_obj instanceof \EE_Belongs_To_Relation ? true : false |
510
|
|
|
) |
511
|
|
|
); |
512
|
|
|
} |
513
|
|
|
return $links; |
514
|
|
|
} |
515
|
|
|
|
516
|
|
|
/** |
517
|
|
|
* Adds the included models indicated in the request to the entity provided |
518
|
|
|
* @param \EEM_Base $model |
519
|
|
|
* @param \WP_REST_Request $rest_request |
520
|
|
|
* @param array $entity_array |
521
|
|
|
* @return array the modified entity |
522
|
|
|
*/ |
523
|
|
|
protected function _include_requested_models( \EEM_Base $model, \WP_REST_Request $rest_request, $entity_array ) { |
524
|
|
|
$includes_for_this_model = $this->explode_and_get_items_prefixed_with( $rest_request->get_param( 'include' ), '' ); |
525
|
|
|
$includes_for_this_model = $this->_remove_model_names_from_array( $includes_for_this_model ); |
526
|
|
|
//if they passed in * or didn't specify any includes, return everything |
527
|
|
|
if( ! in_array( '*', $includes_for_this_model ) |
528
|
|
|
&& ! empty( $includes_for_this_model ) ) { |
529
|
|
|
if( $model->has_primary_key_field() ) { |
530
|
|
|
//always include the primary key. ya just gotta know that at least |
531
|
|
|
$includes_for_this_model[] = $model->primary_key_name(); |
532
|
|
|
} |
533
|
|
|
if( $this->explode_and_get_items_prefixed_with( $rest_request->get_param( 'calculate' ), '' ) ) { |
534
|
|
|
$includes_for_this_model[] = '_calculated_fields'; |
535
|
|
|
} |
536
|
|
|
$entity_array = array_intersect_key( $entity_array, array_flip( $includes_for_this_model ) ); |
537
|
|
|
} |
538
|
|
|
$relation_settings = $this->get_model_version_info()->relation_settings( $model ); |
539
|
|
|
foreach( $relation_settings as $relation_name => $relation_obj ) { |
540
|
|
|
$related_fields_to_include = $this->explode_and_get_items_prefixed_with( |
541
|
|
|
$rest_request->get_param( 'include' ), |
542
|
|
|
$relation_name |
543
|
|
|
); |
544
|
|
|
$related_fields_to_calculate = $this->explode_and_get_items_prefixed_with( |
545
|
|
|
$rest_request->get_param( 'calculate' ), |
546
|
|
|
$relation_name |
547
|
|
|
); |
548
|
|
|
//did they specify they wanted to include a related model, or |
549
|
|
|
//specific fields from a related model? |
550
|
|
|
//or did they specify to calculate a field from a related model? |
551
|
|
|
if( $related_fields_to_include || $related_fields_to_calculate ) { |
|
|
|
|
552
|
|
|
//if so, we should include at least some part of the related model |
553
|
|
|
$pretend_related_request = new \WP_REST_Request(); |
554
|
|
|
$pretend_related_request->set_query_params( |
555
|
|
|
array( |
556
|
|
|
'caps' => $rest_request->get_param( 'caps' ), |
557
|
|
|
'include' => $related_fields_to_include, |
558
|
|
|
'calculate' => $related_fields_to_calculate, |
559
|
|
|
) |
560
|
|
|
); |
561
|
|
|
$pretend_related_request->add_header( 'no_rest_headers', true ); |
562
|
|
|
$related_results = $this->get_entities_from_relation( |
563
|
|
|
$entity_array[ $model->primary_key_name() ], |
564
|
|
|
$relation_obj, |
565
|
|
|
$pretend_related_request |
566
|
|
|
); |
567
|
|
|
$entity_array[ Read::get_related_entity_name( $relation_name, $relation_obj ) ] = $related_results instanceof \WP_Error |
|
|
|
|
568
|
|
|
? null |
569
|
|
|
: $related_results; |
570
|
|
|
} |
571
|
|
|
} |
572
|
|
|
return $entity_array; |
573
|
|
|
} |
574
|
|
|
|
575
|
|
|
/** |
576
|
|
|
* Returns a new array with all the names of models removed. Eg |
577
|
|
|
* array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' ) |
578
|
|
|
* @param array $arr |
579
|
|
|
* @return array |
580
|
|
|
*/ |
581
|
|
|
private function _remove_model_names_from_array( $arr ) { |
582
|
|
|
return array_diff( $arr, array_keys( \EE_Registry::instance()->non_abstract_db_models ) ); |
583
|
|
|
} |
584
|
|
|
/** |
585
|
|
|
* Gets the calculated fields for the response |
586
|
|
|
* |
587
|
|
|
* @param \EEM_Base $model |
588
|
|
|
* @param array $wpdb_row |
589
|
|
|
* @param \WP_REST_Request $rest_request |
590
|
|
|
* @return array the _calculations item in the entity |
591
|
|
|
*/ |
592
|
|
|
protected function _get_entity_calculations( $model, $wpdb_row, $rest_request ) { |
593
|
|
|
$calculated_fields = $this->explode_and_get_items_prefixed_with( |
594
|
|
|
$rest_request->get_param( 'calculate' ), |
595
|
|
|
'' |
596
|
|
|
); |
597
|
|
|
//note: setting calculate=* doesn't do anything |
598
|
|
|
$calculated_fields_to_return = new \stdClass(); |
599
|
|
|
foreach( $calculated_fields as $field_to_calculate ) { |
600
|
|
|
try{ |
601
|
|
|
$calculated_fields_to_return->$field_to_calculate = Model_Data_Translator::prepare_field_value_for_json( |
602
|
|
|
null, |
|
|
|
|
603
|
|
|
$this->_fields_calculator->retrieve_calculated_field_value( |
604
|
|
|
$model, |
605
|
|
|
$field_to_calculate, |
606
|
|
|
$wpdb_row, |
607
|
|
|
$rest_request, |
608
|
|
|
$this |
609
|
|
|
), |
610
|
|
|
$this->get_model_version_info()->requested_version() |
611
|
|
|
); |
612
|
|
|
} catch( Rest_Exception $e ) { |
613
|
|
|
//if we don't have permission to read it, just leave it out. but let devs know about the problem |
614
|
|
|
$this->_set_response_header( |
615
|
|
|
'Notices-Field-Calculation-Errors[' . $e->get_string_code() . '][' . $model->get_this_model_name() . '][' . $field_to_calculate . ']', |
616
|
|
|
$e->getMessage(), |
617
|
|
|
true |
618
|
|
|
); |
619
|
|
|
} |
620
|
|
|
} |
621
|
|
|
return $calculated_fields_to_return; |
622
|
|
|
} |
623
|
|
|
|
624
|
|
|
/** |
625
|
|
|
* Gets the full URL to the resource, taking the requested version into account |
626
|
|
|
* @param string $link_part_after_version_and_slash eg "events/10/datetimes" |
627
|
|
|
* @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes" |
628
|
|
|
*/ |
629
|
|
|
public function get_versioned_link_to( $link_part_after_version_and_slash ) { |
630
|
|
|
return rest_url( |
631
|
|
|
\EED_Core_Rest_Api::ee_api_namespace |
632
|
|
|
. $this->get_model_version_info()->requested_version() |
633
|
|
|
. '/' |
634
|
|
|
. $link_part_after_version_and_slash |
635
|
|
|
); |
636
|
|
|
} |
637
|
|
|
|
638
|
|
|
/** |
639
|
|
|
* Gets the correct lowercase name for the relation in the API according |
640
|
|
|
* to the relation's type |
641
|
|
|
* @param string $relation_name |
642
|
|
|
* @param \EE_Model_Relation_Base $relation_obj |
643
|
|
|
* @return string |
644
|
|
|
*/ |
645
|
|
|
public static function get_related_entity_name( $relation_name, $relation_obj ){ |
646
|
|
|
if( $relation_obj instanceof \EE_Belongs_To_Relation ) { |
647
|
|
|
return strtolower( $relation_name ); |
648
|
|
|
}else{ |
649
|
|
|
return \EEH_Inflector::pluralize_and_lower( $relation_name ); |
650
|
|
|
} |
651
|
|
|
} |
652
|
|
|
|
653
|
|
|
// public function |
654
|
|
|
|
655
|
|
|
|
656
|
|
|
/** |
657
|
|
|
* Gets the one model object with the specified id for the specified model |
658
|
|
|
* @param \EEM_Base $model |
659
|
|
|
* @param \WP_REST_Request $request |
660
|
|
|
* @return array |
661
|
|
|
*/ |
662
|
|
|
public function get_entity_from_model( $model, $request ) { |
663
|
|
|
$query_params = array( array( $model->primary_key_name() => $request->get_param( 'id' ) ),'limit' => 1); |
664
|
|
|
if( $model instanceof \EEM_Soft_Delete_Base ){ |
665
|
|
|
$query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params); |
666
|
|
|
} |
667
|
|
|
$restricted_query_params = $query_params; |
668
|
|
|
$restricted_query_params[ 'caps' ] = $this->validate_context( $request->get_param( 'caps' ) ); |
669
|
|
|
$this->_set_debug_info( 'model query params', $restricted_query_params ); |
670
|
|
|
$model_rows = $model->get_all_wpdb_results( $restricted_query_params ); |
671
|
|
|
if ( ! empty ( $model_rows ) ) { |
672
|
|
|
return $this->create_entity_from_wpdb_result( |
673
|
|
|
$model, |
674
|
|
|
array_shift( $model_rows ), |
675
|
|
|
$request ); |
676
|
|
|
} else { |
677
|
|
|
//ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities |
678
|
|
|
$lowercase_model_name = strtolower( $model->get_this_model_name() ); |
679
|
|
|
$model_rows_found_sans_restrictions = $model->get_all_wpdb_results( $query_params ); |
680
|
|
|
if( ! empty( $model_rows_found_sans_restrictions ) ) { |
681
|
|
|
//you got shafted- it existed but we didn't want to tell you! |
682
|
|
|
return new \WP_Error( |
683
|
|
|
'rest_user_cannot_read', |
684
|
|
|
sprintf( |
685
|
|
|
__( 'Sorry, you cannot read this %1$s. Missing permissions are: %2$s', 'event_espresso' ), |
686
|
|
|
strtolower( $model->get_this_model_name() ), |
687
|
|
|
Capabilities::get_missing_permissions_string( |
688
|
|
|
$model, |
689
|
|
|
$this->validate_context( $request->get_param( 'caps' ) ) ) |
690
|
|
|
), |
691
|
|
|
array( 'status' => 403 ) |
692
|
|
|
); |
693
|
|
|
} else { |
694
|
|
|
//it's not you. It just doesn't exist |
695
|
|
|
return new \WP_Error( |
696
|
|
|
sprintf( 'rest_%s_invalid_id', $lowercase_model_name ), |
697
|
|
|
sprintf( __( 'Invalid %s ID.', 'event_espresso' ), $lowercase_model_name ), |
698
|
|
|
array( 'status' => 404 ) |
699
|
|
|
); |
700
|
|
|
} |
701
|
|
|
} |
702
|
|
|
} |
703
|
|
|
|
704
|
|
|
/** |
705
|
|
|
* If a context is provided which isn't valid, maybe it was added in a future |
706
|
|
|
* version so just treat it as a default read |
707
|
|
|
* |
708
|
|
|
* @param string $context |
709
|
|
|
* @return string array key of EEM_Base::cap_contexts_to_cap_action_map() |
710
|
|
|
*/ |
711
|
|
|
public function validate_context( $context ) { |
712
|
|
|
if( ! $context ) { |
713
|
|
|
$context = \EEM_Base::caps_read; |
714
|
|
|
} |
715
|
|
|
$valid_contexts = \EEM_Base::valid_cap_contexts(); |
716
|
|
|
if( in_array( $context, $valid_contexts ) ){ |
717
|
|
|
return $context; |
718
|
|
|
}else{ |
719
|
|
|
return \EEM_Base::caps_read; |
720
|
|
|
} |
721
|
|
|
} |
722
|
|
|
|
723
|
|
|
|
724
|
|
|
|
725
|
|
|
/** |
726
|
|
|
* Translates API filter get parameter into $query_params array used by EEM_Base::get_all(). |
727
|
|
|
* Note: right now the query parameter keys for fields (and related fields) |
728
|
|
|
* can be left as-is, but it's quite possible this will change someday. |
729
|
|
|
* Also, this method's contents might be candidate for moving to Model_Data_Translator |
730
|
|
|
* |
731
|
|
|
* @param \EEM_Base $model |
732
|
|
|
* @param array $query_parameters from $_GET parameter @see Read:handle_request_get_all |
733
|
|
|
* @return array like what EEM_Base::get_all() expects or FALSE to indicate |
734
|
|
|
* that absolutely no results should be returned |
735
|
|
|
* @throws \EE_Error |
736
|
|
|
*/ |
737
|
|
|
public function create_model_query_params( $model, $query_parameters ) { |
738
|
|
|
$model_query_params = array( ); |
739
|
|
View Code Duplication |
if ( isset( $query_parameters[ 'where' ] ) ) { |
740
|
|
|
$model_query_params[ 0 ] = Model_Data_Translator::prepare_conditions_query_params_for_models( |
741
|
|
|
$query_parameters[ 'where' ], |
742
|
|
|
$model, |
743
|
|
|
$this->get_model_version_info()->requested_version() |
744
|
|
|
); |
745
|
|
|
} |
746
|
|
|
if ( isset( $query_parameters[ 'order_by' ] ) ) { |
747
|
|
|
$order_by = $query_parameters[ 'order_by' ]; |
748
|
|
|
} elseif ( isset( $query_parameters[ 'orderby' ] ) ) { |
749
|
|
|
$order_by = $query_parameters[ 'orderby' ]; |
750
|
|
|
}else{ |
751
|
|
|
$order_by = null; |
752
|
|
|
} |
753
|
|
|
if( $order_by !== null ){ |
754
|
|
|
$model_query_params[ 'order_by' ] = $order_by; |
755
|
|
|
} |
756
|
|
|
if ( isset( $query_parameters[ 'group_by' ] ) ) { |
757
|
|
|
$group_by = $query_parameters[ 'group_by' ]; |
758
|
|
|
} elseif ( isset( $query_parameters[ 'groupby' ] ) ) { |
759
|
|
|
$group_by = $query_parameters[ 'groupby' ]; |
760
|
|
|
}else{ |
761
|
|
|
$group_by = array_keys( $model->get_combined_primary_key_fields() ); |
762
|
|
|
} |
763
|
|
|
if( $group_by !== null ){ |
764
|
|
|
$model_query_params[ 'group_by' ] = $group_by; |
765
|
|
|
} |
766
|
|
View Code Duplication |
if ( isset( $query_parameters[ 'having' ] ) ) { |
767
|
|
|
$model_query_params[ 'having' ] = Model_Data_Translator::prepare_conditions_query_params_for_models( |
768
|
|
|
$query_parameters[ 'having' ], |
769
|
|
|
$model, |
770
|
|
|
$this->get_model_version_info()->requested_version() |
771
|
|
|
); |
772
|
|
|
} |
773
|
|
|
if ( isset( $query_parameters[ 'order' ] ) ) { |
774
|
|
|
$model_query_params[ 'order' ] = $query_parameters[ 'order' ]; |
775
|
|
|
} |
776
|
|
|
if ( isset( $query_parameters[ 'mine' ] ) ){ |
777
|
|
|
$model_query_params = $model->alter_query_params_to_only_include_mine( $model_query_params ); |
778
|
|
|
} |
779
|
|
|
if( isset( $query_parameters[ 'limit' ] ) ) { |
780
|
|
|
//limit should be either a string like '23' or '23,43', or an array with two items in it |
781
|
|
|
if( ! is_array( $query_parameters[ 'limit' ] ) ) { |
782
|
|
|
$limit_array = explode(',', (string)$query_parameters['limit']); |
783
|
|
|
}else { |
784
|
|
|
$limit_array = $query_parameters[ 'limit' ]; |
785
|
|
|
} |
786
|
|
|
$sanitized_limit = array(); |
787
|
|
|
foreach( $limit_array as $key => $limit_part ) { |
788
|
|
|
if( $this->_debug_mode && ( ! is_numeric( $limit_part ) || count( $sanitized_limit ) > 2 ) ) { |
789
|
|
|
throw new \EE_Error( |
790
|
|
|
sprintf( |
791
|
|
|
__( 'An invalid limit filter was provided. It was: %s. If the EE4 JSON REST API weren\'t in debug mode, this message would not appear.', 'event_espresso' ), |
792
|
|
|
json_encode( $query_parameters[ 'limit' ] ) |
793
|
|
|
) |
794
|
|
|
); |
795
|
|
|
} |
796
|
|
|
$sanitized_limit[] = (int)$limit_part; |
797
|
|
|
} |
798
|
|
|
$model_query_params[ 'limit' ] = implode( ',', $sanitized_limit ); |
799
|
|
|
}else{ |
800
|
|
|
$model_query_params[ 'limit' ] = \EED_Core_Rest_Api::get_default_query_limit(); |
801
|
|
|
} |
802
|
|
|
if( isset( $query_parameters[ 'caps' ] ) ) { |
803
|
|
|
$model_query_params[ 'caps' ] = $this->validate_context( $query_parameters[ 'caps' ] ); |
804
|
|
|
}else{ |
805
|
|
|
$model_query_params[ 'caps' ] = \EEM_Base::caps_read; |
806
|
|
|
} |
807
|
|
|
return apply_filters( 'FHEE__Read__create_model_query_params', $model_query_params, $query_parameters, $model ); |
808
|
|
|
} |
809
|
|
|
|
810
|
|
|
|
811
|
|
|
|
812
|
|
|
/** |
813
|
|
|
* Changes the REST-style query params for use in the models |
814
|
|
|
* @deprecated |
815
|
|
|
* @param \EEM_Base $model |
816
|
|
|
* @param array $query_params sub-array from @see EEM_Base::get_all() |
817
|
|
|
* @return array |
818
|
|
|
*/ |
819
|
|
View Code Duplication |
public function prepare_rest_query_params_key_for_models( $model, $query_params ) { |
|
|
|
|
820
|
|
|
$model_ready_query_params = array(); |
821
|
|
|
foreach( $query_params as $key => $value ) { |
822
|
|
|
if( is_array( $value ) ) { |
823
|
|
|
$model_ready_query_params[ $key ] = $this->prepare_rest_query_params_key_for_models( $model, $value ); |
|
|
|
|
824
|
|
|
}else{ |
825
|
|
|
$model_ready_query_params[ $key ] = $value; |
826
|
|
|
} |
827
|
|
|
} |
828
|
|
|
return $model_ready_query_params; |
829
|
|
|
} |
830
|
|
|
|
831
|
|
|
|
832
|
|
|
|
833
|
|
|
/** |
834
|
|
|
* @deprecated |
835
|
|
|
* @param $model |
836
|
|
|
* @param $query_params |
837
|
|
|
* @return array |
838
|
|
|
*/ |
839
|
|
View Code Duplication |
public function prepare_rest_query_params_values_for_models( $model, $query_params ) { |
|
|
|
|
840
|
|
|
$model_ready_query_params = array(); |
841
|
|
|
foreach( $query_params as $key => $value ) { |
842
|
|
|
if( is_array( $value ) ) { |
843
|
|
|
$model_ready_query_params[ $key ] = $this->prepare_rest_query_params_values_for_models( $model, $value ); |
|
|
|
|
844
|
|
|
} else { |
845
|
|
|
$model_ready_query_params[ $key ] = $value; |
846
|
|
|
} |
847
|
|
|
} |
848
|
|
|
return $model_ready_query_params; |
849
|
|
|
} |
850
|
|
|
|
851
|
|
|
/** |
852
|
|
|
* Explodes the string on commas, and only returns items with $prefix followed by a period. |
853
|
|
|
* If no prefix is specified, returns items with no period. |
854
|
|
|
* @param string|array $string_to_explode eg "jibba,jabba, blah, blaabla" or array('jibba', 'jabba' ) |
855
|
|
|
* @param string $prefix "Event" or "foobar" |
856
|
|
|
* @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified |
857
|
|
|
* we only return strings starting with that and a period; if no prefix was specified |
858
|
|
|
* we return all items containing NO periods |
859
|
|
|
*/ |
860
|
|
|
public function explode_and_get_items_prefixed_with( $string_to_explode, $prefix ) { |
861
|
|
|
if( is_string( $string_to_explode ) ) { |
862
|
|
|
$exploded_contents = explode( ',', $string_to_explode ); |
863
|
|
|
} else if( is_array( $string_to_explode ) ) { |
864
|
|
|
$exploded_contents = $string_to_explode; |
865
|
|
|
} else { |
866
|
|
|
$exploded_contents = array(); |
867
|
|
|
} |
868
|
|
|
//if the string was empty, we want an empty array |
869
|
|
|
$exploded_contents = array_filter( $exploded_contents ); |
870
|
|
|
$contents_with_prefix = array(); |
871
|
|
|
foreach( $exploded_contents as $item ) { |
872
|
|
|
$item = trim( $item ); |
873
|
|
|
//if no prefix was provided, so we look for items with no "." in them |
874
|
|
|
if( ! $prefix ) { |
875
|
|
|
//does this item have a period? |
876
|
|
|
if( strpos( $item, '.' ) === false ) { |
877
|
|
|
//if not, then its what we're looking for |
878
|
|
|
$contents_with_prefix[] = $item; |
879
|
|
|
} |
880
|
|
|
} else if( strpos( $item, $prefix . '.' ) === 0 ) { |
881
|
|
|
//this item has the prefix and a period, grab it |
882
|
|
|
$contents_with_prefix[] = substr( |
883
|
|
|
$item, |
884
|
|
|
strpos( $item, $prefix . '.' ) + strlen( $prefix . '.' ) |
885
|
|
|
); |
886
|
|
|
} else if( $item === $prefix ) { |
887
|
|
|
//this item is JUST the prefix |
888
|
|
|
//so let's grab everything after, which is a blank string |
889
|
|
|
$contents_with_prefix[] = ''; |
890
|
|
|
} |
891
|
|
|
} |
892
|
|
|
return $contents_with_prefix; |
893
|
|
|
} |
894
|
|
|
|
895
|
|
|
/** |
896
|
|
|
* @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with. |
897
|
|
|
* Deprecated because its return values were really quite confusing- sometimes it returned |
898
|
|
|
* an empty array (when the include string was blank or '*') or sometimes it returned |
899
|
|
|
* array('*') (when you provided a model and a model of that kind was found). |
900
|
|
|
* Parses the $include_string so we fetch all the field names relating to THIS model |
901
|
|
|
* (ie have NO period in them), or for the provided model (ie start with the model |
902
|
|
|
* name and then a period). |
903
|
|
|
* @param string $include_string @see Read:handle_request_get_all |
904
|
|
|
* @param string $model_name |
905
|
|
|
* @return array of fields for this model. If $model_name is provided, then |
906
|
|
|
* the fields for that model, with the model's name removed from each. |
907
|
|
|
* If $include_string was blank or '*' returns an empty array |
908
|
|
|
*/ |
909
|
|
|
public function extract_includes_for_this_model( $include_string, $model_name = null ) { |
910
|
|
|
if( is_array( $include_string ) ) { |
911
|
|
|
$include_string = implode( ',', $include_string ); |
912
|
|
|
} |
913
|
|
|
if( $include_string === '*' || $include_string === '' ) { |
914
|
|
|
return array(); |
915
|
|
|
} |
916
|
|
|
$includes = explode( ',', $include_string ); |
917
|
|
|
$extracted_fields_to_include = array(); |
918
|
|
|
if( $model_name ){ |
|
|
|
|
919
|
|
|
foreach( $includes as $field_to_include ) { |
920
|
|
|
$field_to_include = trim( $field_to_include ); |
921
|
|
|
if( strpos( $field_to_include, $model_name . '.' ) === 0 ) { |
922
|
|
|
//found the model name at the exact start |
923
|
|
|
$field_sans_model_name = str_replace( $model_name . '.', '', $field_to_include ); |
924
|
|
|
$extracted_fields_to_include[] = $field_sans_model_name; |
925
|
|
|
}elseif( $field_to_include == $model_name ){ |
926
|
|
|
$extracted_fields_to_include[] = '*'; |
927
|
|
|
} |
928
|
|
|
} |
929
|
|
|
}else{ |
930
|
|
|
//look for ones with no period |
931
|
|
|
foreach( $includes as $field_to_include ) { |
932
|
|
|
$field_to_include = trim( $field_to_include ); |
933
|
|
|
if ( |
934
|
|
|
strpos( $field_to_include, '.' ) === false |
935
|
|
|
&& ! $this->get_model_version_info()->is_model_name_in_this_version( $field_to_include ) |
936
|
|
|
) { |
937
|
|
|
$extracted_fields_to_include[] = $field_to_include; |
938
|
|
|
} |
939
|
|
|
} |
940
|
|
|
} |
941
|
|
|
return $extracted_fields_to_include; |
942
|
|
|
|
943
|
|
|
} |
944
|
|
|
} |
945
|
|
|
|
946
|
|
|
|
947
|
|
|
// End of file Read.php |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.