WebDevStudios /
CMB2
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * CMB2 objects/fields endpoint for WordPres REST API. |
||
| 4 | * Allows access to fields registered to a specific box. |
||
| 5 | * |
||
| 6 | * @todo Add better documentation. |
||
| 7 | * @todo Research proper schema. |
||
| 8 | * |
||
| 9 | * @since 2.2.4 |
||
| 10 | * |
||
| 11 | * @category WordPress_Plugin |
||
| 12 | * @package CMB2 |
||
| 13 | * @author WebDevStudios |
||
| 14 | * @license GPL-2.0+ |
||
| 15 | * @link http://webdevstudios.com |
||
| 16 | */ |
||
| 17 | class CMB2_REST_Controller_Fields extends CMB2_REST_Controller_Boxes { |
||
|
0 ignored issues
–
show
|
|||
| 18 | |||
| 19 | /** |
||
| 20 | * Register the routes for the objects of the controller. |
||
| 21 | * |
||
| 22 | * @since 2.2.4 |
||
| 23 | */ |
||
| 24 | public function register_routes() { |
||
| 25 | |||
| 26 | // Returns specific box's fields. |
||
| 27 | register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<cmb_id>[\w-]+)/fields/', array( |
||
| 28 | array( |
||
| 29 | 'methods' => WP_REST_Server::READABLE, |
||
| 30 | 'callback' => array( $this, 'get_items' ), |
||
| 31 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), |
||
| 32 | ), |
||
| 33 | 'schema' => array( $this, 'get_item_schema' ), |
||
| 34 | ) ); |
||
| 35 | |||
| 36 | // Returns specific field data. |
||
| 37 | register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<cmb_id>[\w-]+)/fields/(?P<field_id>[\w-]+)', array( |
||
| 38 | array( |
||
| 39 | 'methods' => WP_REST_Server::READABLE, |
||
| 40 | 'callback' => array( $this, 'get_item' ), |
||
| 41 | 'permission_callback' => array( $this, 'get_item_permissions_check' ), |
||
| 42 | ), |
||
| 43 | array( |
||
| 44 | 'methods' => WP_REST_Server::EDITABLE, |
||
| 45 | 'callback' => array( $this, 'update_field_value' ), |
||
| 46 | 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), |
||
| 47 | 'permission_callback' => array( $this, 'update_field_value_permissions_check' ), |
||
| 48 | ), |
||
| 49 | array( |
||
| 50 | 'methods' => WP_REST_Server::DELETABLE, |
||
| 51 | 'callback' => array( $this, 'delete_field_value' ), |
||
| 52 | 'permission_callback' => array( $this, 'delete_field_value_permissions_check' ), |
||
| 53 | ), |
||
| 54 | 'schema' => array( $this, 'get_item_schema' ), |
||
| 55 | ) ); |
||
| 56 | } |
||
| 57 | |||
| 58 | /** |
||
| 59 | * Get all public CMB2 box fields. |
||
| 60 | * |
||
| 61 | * @since 2.2.4 |
||
| 62 | * |
||
| 63 | * @param WP_REST_Request $request Full data about the request. |
||
| 64 | * @return WP_Error|WP_REST_Response |
||
| 65 | */ |
||
| 66 | public function get_items( $request ) { |
||
| 67 | $this->initiate_rest_read_box( $request, 'fields_read' ); |
||
| 68 | |||
| 69 | if ( is_wp_error( $this->rest_box ) ) { |
||
| 70 | return $this->prepare_item( array( 'error' => $this->rest_box->get_error_message() ) ); |
||
|
0 ignored issues
–
show
The method
get_error_message() does not seem to exist on object<CMB2_REST>.
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. Loading history...
|
|||
| 71 | } |
||
| 72 | |||
| 73 | $fields = array(); |
||
| 74 | foreach ( $this->rest_box->cmb->prop( 'fields', array() ) as $field ) { |
||
| 75 | $field_id = $field['id']; |
||
| 76 | $rest_field = $this->get_rest_field( $field_id ); |
||
| 77 | |||
| 78 | if ( ! is_wp_error( $rest_field ) ) { |
||
| 79 | $fields[ $field_id ] = $this->server->response_to_data( $rest_field, isset( $this->request['_embed'] ) ); |
||
| 80 | } else { |
||
| 81 | $fields[ $field_id ] = array( 'error' => $rest_field->get_error_message() ); |
||
| 82 | } |
||
| 83 | } |
||
| 84 | |||
| 85 | return $this->prepare_item( $fields ); |
||
| 86 | } |
||
| 87 | |||
| 88 | /** |
||
| 89 | * Get one CMB2 field from the collection. |
||
| 90 | * |
||
| 91 | * @since 2.2.4 |
||
| 92 | * |
||
| 93 | * @param WP_REST_Request $request Full data about the request. |
||
| 94 | * @return WP_Error|WP_REST_Response |
||
| 95 | */ |
||
| 96 | public function get_item( $request ) { |
||
| 97 | $this->initiate_rest_read_box( $request, 'field_read' ); |
||
| 98 | |||
| 99 | if ( is_wp_error( $this->rest_box ) ) { |
||
| 100 | return $this->prepare_item( array( 'error' => $this->rest_box->get_error_message() ) ); |
||
|
0 ignored issues
–
show
The method
get_error_message() does not seem to exist on object<CMB2_REST>.
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. Loading history...
|
|||
| 101 | } |
||
| 102 | |||
| 103 | $field = $this->get_rest_field( $this->request->get_param( 'field_id' ) ); |
||
| 104 | |||
| 105 | if ( is_wp_error( $field ) ) { |
||
| 106 | return $this->prepare_item( array( 'error' => $field->get_error_message() ) ); |
||
| 107 | } |
||
| 108 | |||
| 109 | return $this->prepare_item( $field ); |
||
| 110 | } |
||
| 111 | |||
| 112 | /** |
||
| 113 | * Update CMB2 field value. |
||
| 114 | * |
||
| 115 | * @since 2.2.4 |
||
| 116 | * |
||
| 117 | * @param WP_REST_Request $request Full data about the request. |
||
| 118 | * @return WP_Error|WP_REST_Response |
||
| 119 | */ |
||
| 120 | public function update_field_value( $request ) { |
||
| 121 | $this->initiate_rest_read_box( $request, 'field_value_update' ); |
||
| 122 | |||
| 123 | if ( ! $this->request['value'] ) { |
||
| 124 | return $this->prepare_item( array( 'error' => __( 'CMB2 Field value cannot be updated without the value parameter specified.', 'cmb2' ) ) ); |
||
| 125 | } |
||
| 126 | |||
| 127 | $field = $this->rest_box->field_can_write( $this->request->get_param( 'field_id' ), true ); |
||
| 128 | |||
| 129 | return $this->modify_field_value( 'updated', $field ); |
||
|
0 ignored issues
–
show
It seems like
$field defined by $this->rest_box->field_c...aram('field_id'), true) on line 127 can also be of type boolean; however, CMB2_REST_Controller_Fields::modify_field_value() does only seem to accept object<CMB2_Field>, maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. Loading history...
|
|||
| 130 | } |
||
| 131 | |||
| 132 | /** |
||
| 133 | * Delete CMB2 field value. |
||
| 134 | * |
||
| 135 | * @since 2.2.4 |
||
| 136 | * |
||
| 137 | * @param WP_REST_Request $request Full data about the request. |
||
| 138 | * @return WP_Error|WP_REST_Response |
||
| 139 | */ |
||
| 140 | public function delete_field_value( $request ) { |
||
| 141 | $this->initiate_rest_read_box( $request, 'field_value_delete' ); |
||
| 142 | |||
| 143 | $field = $this->rest_box->field_can_write( $this->request->get_param( 'field_id' ), true ); |
||
| 144 | |||
| 145 | return $this->modify_field_value( 'deleted', $field ); |
||
|
0 ignored issues
–
show
It seems like
$field defined by $this->rest_box->field_c...aram('field_id'), true) on line 143 can also be of type boolean; however, CMB2_REST_Controller_Fields::modify_field_value() does only seem to accept object<CMB2_Field>, maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. Loading history...
|
|||
| 146 | } |
||
| 147 | |||
| 148 | /** |
||
| 149 | * Modify CMB2 field value. |
||
| 150 | * |
||
| 151 | * @since 2.2.4 |
||
| 152 | * |
||
| 153 | * @param string $activity The modification activity (updated or deleted). |
||
| 154 | * @param CMB2_Field $field The field object. |
||
| 155 | * @return WP_Error|WP_REST_Response |
||
| 156 | */ |
||
| 157 | public function modify_field_value( $activity, $field ) { |
||
| 158 | |||
| 159 | if ( ! $this->request['object_id'] && ! $this->request['object_type'] ) { |
||
| 160 | return $this->prepare_item( array( 'error' => __( 'CMB2 Field value cannot be modified without the object_id and object_type parameters specified.', 'cmb2' ) ) ); |
||
| 161 | } |
||
| 162 | |||
| 163 | if ( is_wp_error( $this->rest_box ) ) { |
||
| 164 | return $this->prepare_item( array( 'error' => $this->rest_box->get_error_message() ) ); |
||
|
0 ignored issues
–
show
The method
get_error_message() does not seem to exist on object<CMB2_REST>.
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. Loading history...
|
|||
| 165 | } |
||
| 166 | |||
| 167 | if ( ! $field ) { |
||
| 168 | return new WP_Error( 'cmb2_rest_error', __( 'No field found by that id.', 'cmb2' ) ); |
||
| 169 | } |
||
| 170 | |||
| 171 | $field->args["value_{$activity}"] = (bool) 'deleted' === $activity |
||
| 172 | ? $field->remove_data() |
||
| 173 | : $field->save_field( $this->request['value'] ); |
||
| 174 | |||
| 175 | // If options page, save the $activity options |
||
| 176 | if ( 'options-page' == $this->request['object_type'] ) { |
||
| 177 | $field->args["value_{$activity}"] = cmb2_options( $this->request['object_id'] )->set(); |
||
| 178 | } |
||
| 179 | |||
| 180 | $field_data = $this->get_rest_field( $field ); |
||
| 181 | |||
| 182 | if ( is_wp_error( $field_data ) ) { |
||
| 183 | return $this->prepare_item( array( 'error' => $field_data->get_error_message() ) ); |
||
| 184 | } |
||
| 185 | |||
| 186 | return $this->prepare_item( $field_data ); |
||
| 187 | } |
||
| 188 | |||
| 189 | /** |
||
| 190 | * Get a specific field |
||
| 191 | * |
||
| 192 | * @since 2.2.4 |
||
| 193 | * |
||
| 194 | * @param string Field id |
||
| 195 | * @return array|WP_Error |
||
| 196 | */ |
||
| 197 | public function get_rest_field( $field_id ) { |
||
| 198 | $field = $field_id instanceof CMB2_Field ? $field_id : $this->rest_box->field_can_read( $field_id, true ); |
||
| 199 | |||
| 200 | if ( ! $field ) { |
||
| 201 | return new WP_Error( 'cmb2_rest_error', __( 'No field found by that id.', 'cmb2' ) ); |
||
| 202 | } |
||
| 203 | |||
| 204 | $field_data = $this->prepare_field_data( $field ); |
||
|
0 ignored issues
–
show
It seems like
$field defined by $field_id instanceof \CM...n_read($field_id, true) on line 198 can also be of type boolean; however, CMB2_REST_Controller_Fields::prepare_field_data() does only seem to accept object<CMB2_Field>, maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. Loading history...
|
|||
| 205 | $response = rest_ensure_response( $field_data ); |
||
| 206 | |||
| 207 | $response->add_links( $this->prepare_links( $field ) ); |
||
|
0 ignored issues
–
show
It seems like
$field defined by $field_id instanceof \CM...n_read($field_id, true) on line 198 can also be of type boolean; however, CMB2_REST_Controller_Fields::prepare_links() does only seem to accept object<CMB2_Field>, maybe add an additional type check?
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check: /**
* @return array|string
*/
function returnsDifferentValues($x) {
if ($x) {
return 'foo';
}
return array();
}
$x = returnsDifferentValues($y);
if (is_array($x)) {
// $x is an array.
}
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue. Loading history...
|
|||
| 208 | |||
| 209 | return $response; |
||
| 210 | } |
||
| 211 | |||
| 212 | /** |
||
| 213 | * Prepare the field data array for JSON. |
||
| 214 | * |
||
| 215 | * @since 2.2.4 |
||
| 216 | * |
||
| 217 | * @param CMB2_Field $field field object. |
||
| 218 | * |
||
| 219 | * @return array Array of field data. |
||
| 220 | */ |
||
| 221 | protected function prepare_field_data( CMB2_Field $field ) { |
||
| 222 | $field_data = array(); |
||
| 223 | $params_to_ignore = array( 'show_in_rest', 'options' ); |
||
| 224 | $params_to_rename = array( |
||
| 225 | 'label_cb' => 'label', |
||
| 226 | 'options_cb' => 'options', |
||
| 227 | ); |
||
| 228 | |||
| 229 | // Run this first so the js_dependencies arg is populated. |
||
| 230 | $rendered = ( $cb = $field->maybe_callback( 'render_row_cb' ) ) |
||
| 231 | // Ok, callback is good, let's run it. |
||
| 232 | ? $this->get_cb_results( $cb, $field->args(), $field ) |
||
| 233 | : false; |
||
| 234 | |||
| 235 | $field_args = $field->args(); |
||
| 236 | |||
| 237 | foreach ( $field_args as $key => $value ) { |
||
| 238 | if ( in_array( $key, $params_to_ignore, true ) ) { |
||
| 239 | continue; |
||
| 240 | } |
||
| 241 | |||
| 242 | if ( 'options_cb' === $key ) { |
||
| 243 | $value = $field->options(); |
||
| 244 | } elseif ( in_array( $key, CMB2_Field::$callable_fields, true ) ) { |
||
| 245 | |||
| 246 | if ( isset( $this->request['_rendered'] ) ) { |
||
| 247 | $value = $key === 'render_row_cb' ? $rendered : $field->get_param_callback_result( $key ); |
||
| 248 | } elseif ( is_array( $value ) ) { |
||
| 249 | // We need to rewrite callbacks as string as they will cause |
||
| 250 | // JSON recursion errors. |
||
| 251 | $class = is_string( $value[0] ) ? $value[0] : get_class( $value[0] ); |
||
| 252 | $value = $class . '::' . $value[1]; |
||
| 253 | } |
||
| 254 | } |
||
| 255 | |||
| 256 | $key = isset( $params_to_rename[ $key ] ) ? $params_to_rename[ $key ] : $key; |
||
| 257 | |||
| 258 | if ( empty( $value ) || is_scalar( $value ) || is_array( $value ) ) { |
||
| 259 | $field_data[ $key ] = $value; |
||
| 260 | } else { |
||
| 261 | $field_data[ $key ] = sprintf( __( 'Value Error for %s', 'cmb2' ), $key ); |
||
| 262 | } |
||
| 263 | } |
||
| 264 | |||
| 265 | if ( $this->request['object_id'] && $this->request['object_type'] ) { |
||
| 266 | $field_data['value'] = $field->get_data(); |
||
| 267 | } |
||
| 268 | |||
| 269 | return $field_data; |
||
| 270 | } |
||
| 271 | |||
| 272 | /** |
||
| 273 | * Return an array of contextual links for field/fields. |
||
| 274 | * |
||
| 275 | * @since 2.2.4 |
||
| 276 | * |
||
| 277 | * @param CMB2_Field $field Field object to build links from. |
||
| 278 | * |
||
| 279 | * @return array Array of links |
||
| 280 | */ |
||
| 281 | protected function prepare_links( $field ) { |
||
| 282 | $boxbase = $this->namespace_base . '/' . $this->rest_box->cmb->cmb_id; |
||
| 283 | $query_string = $this->get_query_string(); |
||
| 284 | |||
| 285 | $links = array( |
||
| 286 | 'self' => array( |
||
| 287 | 'href' => rest_url( trailingslashit( $boxbase ) . 'fields/' . $field->_id() . $query_string ), |
||
| 288 | ), |
||
| 289 | 'collection' => array( |
||
| 290 | 'href' => rest_url( trailingslashit( $boxbase ) . 'fields' . $query_string ), |
||
| 291 | ), |
||
| 292 | 'up' => array( |
||
| 293 | 'href' => rest_url( $boxbase . $query_string ), |
||
| 294 | ), |
||
| 295 | ); |
||
| 296 | |||
| 297 | // Don't embed boxes when looking at boxes route. |
||
| 298 | if ( '/cmb2/v1/boxes' !== CMB2_REST_Controller::get_intial_route() ) { |
||
| 299 | $links['up']['embeddable'] = true; |
||
| 300 | } |
||
| 301 | |||
| 302 | return $links; |
||
| 303 | } |
||
| 304 | |||
| 305 | } |
||
| 306 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.