'GET', 'callback' => [__CLASS__, 'export_shop_data'], 'permission_callback' => '__return_true', ]); // Sorting rules — απαιτεί token register_rest_route('optisleek', '/sorting', [ [ 'methods' => 'GET', 'callback' => [__CLASS__, 'get_sorting_rules'], 'permission_callback' => [__CLASS__, 'check_token'], ], [ 'methods' => 'POST', 'callback' => [__CLASS__, 'create_sorting_rule'], 'permission_callback' => [__CLASS__, 'check_token'], ], ]); // Cron sync — προστατευμένο με cron secret token register_rest_route('optisleek', '/cron-sync', [ 'methods' => 'GET', 'callback' => [__CLASS__, 'handle_cron_sync'], 'permission_callback' => [__CLASS__, 'check_cron_token'], ]); register_rest_route('optisleek', '/sorting/(?P\d+)', [ [ 'methods' => 'PUT', 'callback' => [__CLASS__, 'update_sorting_rule'], 'permission_callback' => [__CLASS__, 'check_token'], ], [ 'methods' => 'PATCH', 'callback' => [__CLASS__, 'update_sorting_rule'], 'permission_callback' => [__CLASS__, 'check_token'], ], [ 'methods' => 'DELETE', 'callback' => [__CLASS__, 'delete_sorting_rule'], 'permission_callback' => [__CLASS__, 'check_token'], ], ]); } // ── Auth ────────────────────────────────────────────────────────────────── public static function check_cron_token(WP_REST_Request $request): bool { $saved = trim((string) get_option('optisleek_cron_secret', '')); if (!$saved) return false; $sent = (string) ($request->get_param('cron_token') ?? ''); return $sent !== '' && hash_equals($saved, $sent); } public static function check_token(WP_REST_Request $request): bool { $saved = trim((string) get_option('api_token', '')); if (!$saved) return false; $sent = $request->get_header('X-Api-Token') ?: $request->get_param('api_token'); return $sent !== null && hash_equals($saved, (string) $sent); } // ── Cron sync endpoint ──────────────────────────────────────────────────── public static function handle_cron_sync(WP_REST_Request $request) { $result = Optisleek_Sorting::sync_from_tool(); Optisleek_Sorting::write_log($result, 'cron'); if ($result['success']) { return rest_ensure_response([ 'success' => true, 'synced' => $result['synced'], 'message' => "Συγχρονίστηκαν {$result['synced']} κανόνες.", ]); } return new WP_REST_Response([ 'success' => false, 'message' => $result['message'] ?? 'Σφάλμα', ], 500); } // ── Products (υπάρχον) ──────────────────────────────────────────────────── public static function export_shop_data(WP_REST_Request $request) { // Προαιρετική σελιδοποίηση / incremental sync — χωρίς παραμέτρους η // απάντηση είναι ακριβώς ίδια με πριν (πλήρης κατάλογος). // ?page=1&per_page=100 → σελιδοποίηση (άδειο products = τέλος) // ?modified_after=2026-08-01 → μόνο όσα άλλαξαν από τότε $page = max(0, (int) $request->get_param('page')); $per_page = max(0, min(500, (int) $request->get_param('per_page'))); $modified_after = sanitize_text_field((string) $request->get_param('modified_after')); return rest_ensure_response([ 'shop' => [ 'brands' => Optisleek_Product_Export::optisleek_get_brands(), 'categories' => Optisleek_Product_Export::optisleek_get_categories(), 'attribute_templates' => Optisleek_Product_Export::optisleek_get_attribute_templates(), 'attributes' => Optisleek_Product_Export::optisleek_get_attributes(), 'products' => Optisleek_Product_Export::optisleek_get_products($page, $per_page, $modified_after), ] ]); } // ── Sorting endpoints ───────────────────────────────────────────────────── public static function get_sorting_rules(WP_REST_Request $request) { $rules = Optisleek_Sorting::get_all(); $data = array_map(function ($rule) { return [ 'id' => (int) $rule->id, 'category_ids' => json_decode($rule->category_ids, true) ?: [], 'product_ids' => json_decode($rule->product_ids, true) ?: [], 'enabled' => (bool) $rule->enabled, 'updated_at' => $rule->updated_at, ]; }, $rules); return rest_ensure_response($data); } public static function create_sorting_rule(WP_REST_Request $request) { $category_ids = array_map('intval', (array) ($request->get_param('category_ids') ?? [])); $product_ids = array_map('intval', (array) ($request->get_param('product_ids') ?? [])); $enabled = (bool) ($request->get_param('enabled') ?? true); if (empty($product_ids)) { return new WP_REST_Response(['message' => 'product_ids is required'], 422); } $id = Optisleek_Sorting::create($category_ids, $product_ids, $enabled); if (!$id) { return new WP_REST_Response(['message' => 'Failed to create rule'], 500); } return new WP_REST_Response(Optisleek_Sorting::get_by_id($id), 201); } public static function update_sorting_rule(WP_REST_Request $request) { $id = (int) $request->get_param('id'); $rule = Optisleek_Sorting::get_by_id($id); if (!$rule) { return new WP_REST_Response(['message' => 'Rule not found'], 404); } $fields = []; if ($request->has_param('category_ids')) { $fields['category_ids'] = wp_json_encode( array_values(array_map('intval', (array) $request->get_param('category_ids'))) ); } if ($request->has_param('product_ids')) { $fields['product_ids'] = wp_json_encode( array_values(array_map('intval', (array) $request->get_param('product_ids'))) ); } if ($request->has_param('enabled')) { $fields['enabled'] = $request->get_param('enabled') ? 1 : 0; } if (empty($fields)) { return new WP_REST_Response(['message' => 'No fields to update'], 422); } Optisleek_Sorting::update($id, $fields); return rest_ensure_response(Optisleek_Sorting::get_by_id($id)); } public static function delete_sorting_rule(WP_REST_Request $request) { $id = (int) $request->get_param('id'); if (!Optisleek_Sorting::get_by_id($id)) { return new WP_REST_Response(['message' => 'Rule not found'], 404); } Optisleek_Sorting::delete($id); return new WP_REST_Response(null, 204); } }