'GET', 'callback' => [__CLASS__, 'check_update'], 'permission_callback' => '__return_true', 'args' => [ 'license_key' => ['required' => true, 'type' => 'string'], 'slug' => ['required' => true, 'type' => 'string'], 'version' => ['required' => true, 'type' => 'string'], 'site_url' => ['required' => false, 'type' => 'string'], ], ]); // Also support POST for update check (some clients prefer this) register_rest_route($namespace, '/software/check', [ 'methods' => 'POST', 'callback' => [__CLASS__, 'check_update'], 'permission_callback' => '__return_true', ]); // Download file register_rest_route($namespace, '/software/download', [ 'methods' => 'GET', 'callback' => [__CLASS__, 'download'], 'permission_callback' => '__return_true', 'args' => [ 'token' => ['required' => true, 'type' => 'string'], ], ]); // Get changelog register_rest_route($namespace, '/software/changelog', [ 'methods' => 'GET', 'callback' => [__CLASS__, 'get_changelog'], 'permission_callback' => '__return_true', 'args' => [ 'slug' => ['required' => true, 'type' => 'string'], 'version' => ['required' => false, 'type' => 'string'], ], ]); // Admin endpoints (requires manage_woocommerce) // Get all versions for a product register_rest_route($namespace, '/software/products/(?P\d+)/versions', [ 'methods' => 'GET', 'callback' => [__CLASS__, 'get_versions'], 'permission_callback' => function () { return current_user_can('manage_woocommerce'); }, ]); // Add new version register_rest_route($namespace, '/software/products/(?P\d+)/versions', [ 'methods' => 'POST', 'callback' => [__CLASS__, 'add_version'], 'permission_callback' => function () { return current_user_can('manage_woocommerce'); }, ]); } /** * Check for updates */ public static function check_update(WP_REST_Request $request) { // Check if module is enabled if (!ModuleRegistry::is_enabled('software')) { return new WP_REST_Response([ 'success' => false, 'error' => 'module_disabled', 'message' => __('Software distribution module is not enabled', 'woonoow'), ], 503); } // Get parameters from GET or POST body $params = $request->get_method() === 'POST' ? $request->get_json_params() : $request->get_query_params(); $license_key = sanitize_text_field($params['license_key'] ?? ''); $slug = sanitize_text_field($params['slug'] ?? ''); $current_version = sanitize_text_field($params['version'] ?? ''); $site_url = esc_url_raw($params['site_url'] ?? ''); if (empty($license_key) || empty($slug) || empty($current_version)) { return new WP_REST_Response([ 'success' => false, 'error' => 'missing_params', 'message' => __('Missing required parameters: license_key, slug, version', 'woonoow'), ], 400); } // Log the check (optional - for analytics) do_action('woonoow/software/update_check', $slug, $current_version, $site_url, $license_key); $result = SoftwareManager::check_update($license_key, $slug, $current_version); $status_code = isset($result['success']) && $result['success'] === false ? 400 : 200; return new WP_REST_Response($result, $status_code); } /** * Download file */ public static function download(WP_REST_Request $request) { // Check if module is enabled if (!ModuleRegistry::is_enabled('software')) { return new WP_REST_Response([ 'success' => false, 'error' => 'module_disabled', 'message' => __('Software distribution module is not enabled', 'woonoow'), ], 503); } $token = sanitize_text_field($request->get_param('token')); if (empty($token)) { return new WP_REST_Response([ 'success' => false, 'error' => 'missing_token', 'message' => __('Download token is required', 'woonoow'), ], 400); } // Validate token $download = SoftwareManager::validate_download_token($token); if (is_wp_error($download)) { return new WP_REST_Response([ 'success' => false, 'error' => $download->get_error_code(), 'message' => $download->get_error_message(), ], 403); } // Validate license is still active $license = LicenseManager::get_license($download['license_id']); if (!$license || $license['status'] !== 'active') { return new WP_REST_Response([ 'success' => false, 'error' => 'license_inactive', 'message' => __('License is no longer active', 'woonoow'), ], 403); } // Serve the file SoftwareManager::serve_file($download['product_id']); // Note: serve_file calls exit, so this won't be reached return new WP_REST_Response(['success' => true], 200); } /** * Get changelog */ public static function get_changelog(WP_REST_Request $request) { $slug = sanitize_text_field($request->get_param('slug')); $version = sanitize_text_field($request->get_param('version')); if (empty($slug)) { return new WP_REST_Response([ 'success' => false, 'error' => 'missing_slug', 'message' => __('Software slug is required', 'woonoow'), ], 400); } // Get product by slug $product = SoftwareManager::get_product_by_slug($slug); if (!$product) { return new WP_REST_Response([ 'success' => false, 'error' => 'product_not_found', 'message' => __('Software product not found', 'woonoow'), ], 404); } // Get all versions or specific version if ($version) { $changelog = SoftwareManager::get_version_changelog($product->get_id(), $version); if (!$changelog) { return new WP_REST_Response([ 'success' => false, 'error' => 'version_not_found', 'message' => __('Version not found', 'woonoow'), ], 404); } return new WP_REST_Response([ 'slug' => $slug, 'version' => $changelog['version'], 'release_date' => $changelog['release_date'], 'changelog' => $changelog['changelog'], ], 200); } // Get all versions $versions = SoftwareManager::get_all_versions($product->get_id()); return new WP_REST_Response([ 'slug' => $slug, 'versions' => array_map(function ($v) { return [ 'version' => $v['version'], 'release_date' => $v['release_date'], 'changelog' => $v['changelog'], 'download_count' => (int) $v['download_count'], ]; }, $versions), ], 200); } /** * Get versions for a product (admin) */ public static function get_versions(WP_REST_Request $request) { $product_id = (int) $request->get_param('product_id'); $product = wc_get_product($product_id); if (!$product) { return new WP_REST_Response([ 'success' => false, 'error' => 'product_not_found', ], 404); } $versions = SoftwareManager::get_all_versions($product_id); $config = SoftwareManager::get_product_config($product_id); return new WP_REST_Response([ 'product_id' => $product_id, 'config' => $config, 'versions' => $versions, ], 200); } /** * Add new version (admin) */ public static function add_version(WP_REST_Request $request) { $product_id = (int) $request->get_param('product_id'); $params = $request->get_json_params(); $version = sanitize_text_field($params['version'] ?? ''); $changelog = wp_kses_post($params['changelog'] ?? ''); $set_current = (bool) ($params['set_current'] ?? true); if (empty($version)) { return new WP_REST_Response([ 'success' => false, 'error' => 'missing_version', 'message' => __('Version number is required', 'woonoow'), ], 400); } $product = wc_get_product($product_id); if (!$product) { return new WP_REST_Response([ 'success' => false, 'error' => 'product_not_found', ], 404); } $result = SoftwareManager::add_version($product_id, $version, $changelog, $set_current); if (is_wp_error($result)) { return new WP_REST_Response([ 'success' => false, 'error' => $result->get_error_code(), 'message' => $result->get_error_message(), ], 400); } return new WP_REST_Response([ 'success' => true, 'version_id' => $result, 'message' => __('Version added successfully', 'woonoow'), ], 201); } }