322 lines
10 KiB
PHP
322 lines
10 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Software Distribution API Controller
|
|
*
|
|
* REST API endpoints for software update checking and downloads.
|
|
*
|
|
* @package WooNooW\Api
|
|
*/
|
|
|
|
namespace WooNooW\Api;
|
|
|
|
if (!defined('ABSPATH')) exit;
|
|
|
|
use WP_REST_Request;
|
|
use WP_REST_Response;
|
|
use WP_Error;
|
|
use WooNooW\Core\ModuleRegistry;
|
|
use WooNooW\Modules\Software\SoftwareManager;
|
|
use WooNooW\Modules\Licensing\LicenseManager;
|
|
|
|
class SoftwareController
|
|
{
|
|
/**
|
|
* Register REST routes
|
|
*/
|
|
public static function register_routes()
|
|
{
|
|
$namespace = 'woonoow/v1';
|
|
|
|
// Public endpoints (authenticated via license key)
|
|
|
|
// Check for updates
|
|
register_rest_route($namespace, '/software/check', [
|
|
'methods' => '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<product_id>\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<product_id>\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);
|
|
}
|
|
}
|