PluginProbe
Extendify / 3.1.5
Extendify v3.1.5
3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 0.7.0 All 126 releases
extendify / app / QuickEdit / Controllers / WCProductController.php

WCProductController.php in Extendify 3.1.5, at app/QuickEdit/Controllers/WCProductController.php

141 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Extendify\QuickEdit\Controllers;
4
5 defined('ABSPATH') || die('No direct access.');
6
7 use Extendify\Config;
8
9 // Bypasses SaveController; product data lives on the product object,
10 // not in post_content. Image = featured image (set_post_thumbnail).
11 class WCProductController
12 {
13 public static function init()
14 {
15 add_action('rest_api_init', [self::class, 'registerRoutes']);
16 }
17
18 public static function registerRoutes()
19 {
20 register_rest_route('extendify/v1', '/quick-edit/product', [
21 [
22 'methods' => 'GET',
23 'permission_callback' => [self::class, 'permissionCallback'],
24 'callback' => [self::class, 'handle'],
25 ],
26 [
27 'methods' => 'POST',
28 'permission_callback' => [self::class, 'permissionCallback'],
29 'callback' => [self::class, 'handle'],
30 ],
31 ]);
32 }
33
34 public static function permissionCallback(): bool
35 {
36 // Per-product check runs in handle() once we have the product_id.
37 return current_user_can(Config::$requiredCapability);
38 }
39
40 public static function handle(\WP_REST_Request $req)
41 {
42 $pid = (int) $req->get_param('product_id');
43 if ($pid <= 0) {
44 return new \WP_REST_Response(['error' => 'product_id required'], 400);
45 }
46 if (get_post_type($pid) !== 'product') {
47 return new \WP_REST_Response(['error' => 'not a product'], 400);
48 }
49 if (!current_user_can('edit_post', $pid)) {
50 return new \WP_REST_Response(['error' => 'cannot edit this product'], 403);
51 }
52 if (!function_exists('wc_get_product')) {
53 return new \WP_REST_Response(['error' => 'WooCommerce not active'], 500);
54 }
55
56 if ($req->get_method() === 'GET') {
57 $post = get_post($pid);
58 $product = wc_get_product($pid);
59 $thumb = (int) get_post_thumbnail_id($pid);
60 $thumbUrl = $thumb ? wp_get_attachment_image_url($thumb, 'medium') : '';
61 return new \WP_REST_Response([
62 'name' => $post ? $post->post_title : '',
63 'short_description' => $post ? $post->post_excerpt : '',
64 'description' => $post ? $post->post_content : '',
65 'regular_price' => $product ? (string) $product->get_regular_price() : '',
66 'sale_price' => $product ? (string) $product->get_sale_price() : '',
67 'image_id' => $thumb,
68 'image_url' => $thumbUrl ?: '',
69 ]);
70 }
71
72 $field = (string) $req->get_param('field');
73 $value = $req->get_param('value');
74
75 if ($field === 'name') {
76 $res = wp_update_post([
77 'ID' => $pid,
78 'post_title' => wp_slash(sanitize_text_field((string) $value)),
79 ], true);
80 if (is_wp_error($res)) {
81 return new \WP_REST_Response(['error' => $res->get_error_message()], 500);
82 }
83 } elseif ($field === 'short_description') {
84 $res = wp_update_post([
85 'ID' => $pid,
86 'post_excerpt' => wp_slash(wp_kses_post((string) $value)),
87 ], true);
88 if (is_wp_error($res)) {
89 return new \WP_REST_Response(['error' => $res->get_error_message()], 500);
90 }
91 } elseif ($field === 'description') {
92 $res = wp_update_post([
93 'ID' => $pid,
94 'post_content' => wp_slash(wp_kses_post((string) $value)),
95 ], true);
96 if (is_wp_error($res)) {
97 return new \WP_REST_Response(['error' => $res->get_error_message()], 500);
98 }
99 } elseif ($field === 'price') {
100 if (!is_array($value)) {
101 return new \WP_REST_Response(
102 ['error' => 'price expects {regular, sale}'],
103 400
104 );
105 }
106 $product = wc_get_product($pid);
107 if (!$product) {
108 return new \WP_REST_Response(['error' => 'product not found'], 404);
109 }
110 $regular = isset($value['regular']) ? wc_format_decimal($value['regular']) : '';
111 $sale = isset($value['sale']) && $value['sale'] !== ''
112 ? wc_format_decimal($value['sale'])
113 : '';
114 $product->set_regular_price($regular);
115 $product->set_sale_price($sale);
116 // _price is the displayed price; set_regular/set_sale don't auto-sync it.
117 if ($sale !== '' && (float) $sale < (float) $regular) {
118 $product->set_price($sale);
119 } else {
120 $product->set_price($regular);
121 }
122 $product->save();
123 } elseif ($field === 'image') {
124 $attId = (int) $value;
125 if ($attId <= 0) {
126 return new \WP_REST_Response(['error' => 'attachment_id required'], 400);
127 }
128 if (!wp_attachment_is_image($attId)) {
129 return new \WP_REST_Response(['error' => 'not an image attachment'], 400);
130 }
131 set_post_thumbnail($pid, $attId);
132 } else {
133 return new \WP_REST_Response(
134 ['error' => 'unknown field: ' . $field],
135 400
136 );
137 }
138 return new \WP_REST_Response(['ok' => true]);
139 }
140 }
141