/** * Prepare a single webhook for create or update. * * @param WP_REST_Request $request Request object. * @return WP_Error|stdClass $data Post object. */ protected function prepare_item_for_database($request) { global $wpdb; $data = new stdClass(); // Post ID. if (isset($request['id'])) { $data->ID = absint($request['id']); } // Validate required POST fields. if ('POST' === $request->get_method() && empty($data->ID)) { // @codingStandardsIgnoreStart $data->post_title = !empty($request['name']) ? $request['name'] : sprintf(__('Webhook created on %s', 'woocommerce'), strftime(_x('%b %d, %Y @ %I:%M %p', 'Webhook created on date parsed by strftime', 'woocommerce'))); // @codingStandardsIgnoreEnd // Post author. $data->post_author = get_current_user_id(); // Post password. $password = strlen(uniqid('webhook_')); $data->post_password = $password > 20 ? substr($password, 0, 20) : $password; // Post status. $data->post_status = 'publish'; } else { // Allow edit post title. if (!empty($request['name'])) { $data->post_title = $request['name']; } } // Comment status. $data->comment_status = 'closed'; // Ping status. $data->ping_status = 'closed'; /** * Filter the query_vars used in `get_items` for the constructed query. * * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being * prepared for insertion. * * @param stdClass $data An object representing a single item prepared * for inserting or updating the database. * @param WP_REST_Request $request Request object. */ return apply_filters("woocommerce_rest_pre_insert_{$this->post_type}", $data, $request); }
/** * Hooks into the REST API output to print XML instead of JSON. * * This is only done for the oEmbed API endpoint, * which supports both formats. * * @access private * @since 4.4.0 * * @param bool $served Whether the request has already been served. * @param WP_HTTP_ResponseInterface $result Result to send to the client. Usually a WP_REST_Response. * @param WP_REST_Request $request Request used to generate the response. * @param WP_REST_Server $server Server instance. * @return true */ function _oembed_rest_pre_serve_request($served, $result, $request, $server) { $params = $request->get_params(); if ('/oembed/1.0/embed' !== $request->get_route() || 'GET' !== $request->get_method()) { return $served; } if (!isset($params['format']) || 'xml' !== $params['format']) { return $served; } // Embed links inside the request. $data = $server->response_to_data($result, false); if (404 === $result->get_status()) { $data = $data[0]; } if (!class_exists('SimpleXMLElement')) { status_header(501); die(get_status_header_desc(501)); } $result = _oembed_create_xml($data); // Bail if there's no XML. if (!$result) { status_header(501); return get_status_header_desc(501); } if (!headers_sent()) { $server->send_header('Content-Type', 'text/xml; charset=' . get_option('blog_charset')); } echo $result; return true; }
/** * Hooks into the REST API output to print XML instead of JSON. * * @access private * * @param bool $served Whether the request has already been served. * @param WP_HTTP_ResponseInterface $result Result to send to the client. Usually a WP_REST_Response. * @param WP_REST_Request $request Request used to generate the response. * @param WP_REST_Server $server Server instance. * @return true */ function _oembed_rest_pre_serve_request($served, $result, $request, $server) { $params = $request->get_params(); if ('/wp/v2/oembed' !== $request->get_route() || 'GET' !== $request->get_method()) { return $served; } if (!isset($params['format']) || 'xml' !== $params['format']) { return $served; } // Embed links inside the request. $data = $server->response_to_data($result, false); if (404 === $result->get_status()) { $data = $data[0]; } /** * Filter the XML response. * * @param array $data The original oEmbed response data. */ $result = apply_filters('oembed_xml_response', $data); // Bail if there's no XML. if (!is_string($result)) { status_header(501); die('Not implemented'); } if (!headers_sent()) { $server->send_header('Content-Type', 'text/xml; charset=' . get_option('blog_charset')); } echo $result; return true; }
/** * Bulk create, update and delete items. * * @since 2.7.0 * @param WP_REST_Request $request Full details about the request. * @return array Of WP_Error or WP_REST_Response. */ public function batch_items($request) { $items = array_filter($request->get_params()); $params = $request->get_url_params(); $product_id = $params['product_id']; $body_params = array(); foreach (array('update', 'create', 'delete') as $batch_type) { if (!empty($items[$batch_type])) { $injected_items = array(); foreach ($items[$batch_type] as $item) { $injected_items[] = array_merge(array('product_id' => $product_id), $item); } $body_params[$batch_type] = $injected_items; } } $request = new WP_REST_Request($request->get_method()); $request->set_body_params($body_params); return parent::batch_items($request); }
/** * Handles OPTIONS requests for the server. * * This is handled outside of the server code, as it doesn't obey normal route * mapping. * * @since 4.4.0 * * @param mixed $response Current response, either response or `null` to indicate pass-through. * @param WP_REST_Server $handler ResponseHandler instance (usually WP_REST_Server). * @param WP_REST_Request $request The request that was used to make current response. * @return WP_REST_Response Modified response, either response or `null` to indicate pass-through. */ function rest_handle_options_request($response, $handler, $request) { if (!empty($response) || $request->get_method() !== 'OPTIONS') { return $response; } $response = new WP_REST_Response(); $data = array(); $accept = array(); foreach ($handler->get_routes() as $route => $endpoints) { $match = preg_match('@^' . $route . '$@i', $request->get_route(), $args); if (!$match) { continue; } $data = $handler->get_data_for_route($route, $endpoints, 'help'); $accept = array_merge($accept, $data['methods']); break; } $response->header('Accept', implode(', ', $accept)); $response->set_data($data); return $response; }
/** * Handles OPTIONS requests for the server. * * This is handled outside of the server code, as it doesn't obey normal route * mapping. * * @since 4.4.0 * * @param mixed $response Current response, either response or `null` to indicate pass-through. * @param WP_REST_Server $handler ResponseHandler instance (usually WP_REST_Server). * @param WP_REST_Request $request The request that was used to make current response. * @return WP_REST_Response Modified response, either response or `null` to indicate pass-through. */ function rest_handle_options_request($response, $handler, $request) { if (!empty($response) || $request->get_method() !== 'OPTIONS') { return $response; } $response = new WP_REST_Response(); $data = array(); foreach ($handler->get_routes() as $route => $endpoints) { $match = preg_match('@^' . $route . '$@i', $request->get_route()); if (!$match) { continue; } $data = $handler->get_data_for_route($route, $endpoints, 'help'); $response->set_matched_route($route); break; } $response->set_data($data); return $response; }
/** * Hooks into the REST API output to print XML instead of JSON. * * @param bool $served Whether the request has already been served. * @param WP_HTTP_ResponseInterface $result Result to send to the client. Usually a WP_REST_Response. * @param WP_REST_Request $request Request used to generate the response. * @param WP_REST_Server $server Server instance. * * @return bool */ public function rest_pre_serve_request($served, $result, $request, $server) { $params = $request->get_params(); if ('/wp/v2/oembed' !== $request->get_route() || 'xml' !== $params['format']) { return $served; } if ('HEAD' === $request->get_method()) { return $served; } if (!headers_sent()) { $server->send_header('Content-Type', 'text/xml; charset=' . get_option('blog_charset')); } // Embed links inside the request. $result = $server->response_to_data($result, false); $oembed = new SimpleXMLElement('<oembed></oembed>'); foreach ($result as $key => $value) { if (is_array($value)) { $element = $oembed->addChild($key); foreach ($value as $k => $v) { $element->addChild($k, $v); } continue; } $oembed->addChild($key, $value); } echo $oembed->asXML(); return true; }
/** * Prepare a single coupon for create or update. * * @param WP_REST_Request $request Request object. * @return WP_Error|stdClass $data Post object. */ protected function prepare_item_for_database($request) { global $wpdb; $id = isset($request['id']) ? absint($request['id']) : 0; $coupon = new WC_Coupon($id); $schema = $this->get_item_schema(); $data_keys = array_keys(array_filter($schema['properties'], array($this, 'filter_writable_props'))); // BW compat if ($request['exclude_product_ids']) { $request['excluded_product_ids'] = $request['exclude_product_ids']; } if ($request['expiry_date']) { $request['date_expires'] = $request['expiry_date']; } // Validate required POST fields. if ('POST' === $request->get_method() && 0 === $coupon->get_id()) { if (empty($request['code'])) { return new WP_Error('woocommerce_rest_empty_coupon_code', sprintf(__('The coupon code cannot be empty.', 'woocommerce'), 'code'), array('status' => 400)); } } // Handle all writable props foreach ($data_keys as $key) { $value = $request[$key]; if (!is_null($value)) { switch ($key) { case 'code': $coupon_code = apply_filters('woocommerce_coupon_code', $value); $id = $coupon->get_id() ? $coupon->get_id() : 0; $id_from_code = wc_get_coupon_id_by_code($coupon_code, $id); if ($id_from_code) { return new WP_Error('woocommerce_rest_coupon_code_already_exists', __('The coupon code already exists', 'woocommerce'), array('status' => 400)); } $coupon->set_code($coupon_code); break; case 'meta_data': if (is_array($value)) { foreach ($value as $meta) { $coupon->update_meta_data($meta['key'], $meta['value'], $meta['id']); } } break; case 'description': $coupon->set_description(wp_filter_post_kses($value)); break; default: if (is_callable(array($coupon, "set_{$key}"))) { $coupon->{"set_{$key}"}($value); } break; } } } /** * Filter the query_vars used in `get_items` for the constructed query. * * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being * prepared for insertion. * * @param WC_Coupon $coupon The coupon object. * @param WP_REST_Request $request Request object. */ return apply_filters("woocommerce_rest_pre_insert_{$this->post_type}", $coupon, $request); }
/** * Prepare a single coupon for create or update. * * @param WP_REST_Request $request Request object. * @return WP_Error|stdClass $data Post object. */ protected function prepare_item_for_database($request) { global $wpdb; $data = new stdClass(); // ID. if (isset($request['id'])) { $data->ID = absint($request['id']); } $schema = $this->get_item_schema(); // Validate required POST fields. if ('POST' === $request->get_method() && empty($data->ID)) { if (empty($request['code'])) { return new WP_Error('woocommerce_rest_empty_coupon_code', sprintf(__('The coupon code cannot be empty.', 'woocommerce'), 'code'), array('status' => 400)); } } // Code. if (!empty($schema['properties']['code']) && !empty($request['code'])) { $coupon_code = apply_filters('woocommerce_coupon_code', $request['code']); $id = isset($data->ID) ? $data->ID : 0; // Check for duplicate coupon codes. $coupon_found = $wpdb->get_var($wpdb->prepare("\n\t\t\t\tSELECT {$wpdb->posts}.ID\n\t\t\t\tFROM {$wpdb->posts}\n\t\t\t\tWHERE {$wpdb->posts}.post_type = 'shop_coupon'\n\t\t\t\tAND {$wpdb->posts}.post_status = 'publish'\n\t\t\t\tAND {$wpdb->posts}.post_title = '%s'\n\t\t\t\tAND {$wpdb->posts}.ID != %s\n\t\t\t ", $coupon_code, $id)); if ($coupon_found) { return new WP_Error('woocommerce_rest_coupon_code_already_exists', __('The coupon code already exists', 'woocommerce'), array('status' => 400)); } $data->post_title = $coupon_code; } // Content. $data->post_content = ''; // Excerpt. if (!empty($schema['properties']['excerpt']) && isset($request['description'])) { $data->post_excerpt = wp_filter_post_kses($request['description']); } // Post type. $data->post_type = $this->post_type; // Post status. $data->post_status = 'publish'; // Comment status. $data->comment_status = 'closed'; // Ping status. $data->ping_status = 'closed'; /** * Filter the query_vars used in `get_items` for the constructed query. * * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being * prepared for insertion. * * @param stdClass $data An object representing a single item prepared * for inserting or updating the database. * @param WP_REST_Request $request Request object. */ return apply_filters("woocommerce_rest_pre_insert_{$this->post_type}", $data, $request); }
/** * Check if user is allowed to perform the update. * * @since 4.3.0 * * @param WP_REST_Request $request * * @return bool */ public function can_request($request) { if ('GET' === $request->get_method()) { return current_user_can('jetpack_admin_page'); } else { $module = Jetpack_Core_Json_Api_Endpoints::get_module_requested(); // User is trying to create, regenerate or delete its PbE || ATD settings. if ('post-by-email' === $module || 'after-the-deadline' === $module) { return current_user_can('edit_posts') && current_user_can('jetpack_admin_page'); } return current_user_can('jetpack_configure_modules'); } }
/** * Bulk create, update and delete items. * * @since 2.7.0 * @param WP_REST_Request $request Full details about the request. * @return array Of WP_Error or WP_REST_Response. */ public function batch_items($request) { // Get the request params. $items = array_filter($request->get_params()); /* * Since our batch settings update is group-specific and matches based on the route, * we inject the URL parameters (containing group) into the batch items */ if (!empty($items['update'])) { $to_update = array(); foreach ($items['update'] as $item) { $to_update[] = array_merge($request->get_url_params(), $item); } $request = new WP_REST_Request($request->get_method()); $request->set_body_params(array('update' => $to_update)); } return parent::batch_items($request); }