Files
twilio-wp-plugin/includes/class-twp-auto-updater.php

292 lines
10 KiB
PHP
Raw Normal View History

Add mobile app infrastructure and Gitea auto-update support This commit adds comprehensive mobile app support to enable a native Android app that won't timeout or sleep when the screen goes dark. New Features: - JWT-based authentication system (no WordPress session dependency) - REST API endpoints for mobile app (agent status, queue management, call control) - Server-Sent Events (SSE) for real-time updates to mobile app - Firebase Cloud Messaging (FCM) integration for push notifications - Gitea-based automatic plugin updates - Mobile app admin settings page New Files: - includes/class-twp-mobile-auth.php - JWT authentication with login/refresh/logout - includes/class-twp-mobile-api.php - REST API endpoints under /twilio-mobile/v1 - includes/class-twp-mobile-sse.php - Real-time event streaming - includes/class-twp-fcm.php - Push notification handling - includes/class-twp-auto-updater.php - Gitea-based auto-updates - admin/mobile-app-settings.php - Admin configuration page Modified Files: - includes/class-twp-activator.php - Added twp_mobile_sessions table - includes/class-twp-core.php - Load and initialize mobile classes - admin/class-twp-admin.php - Added Mobile App menu item and settings page Database Changes: - New table: twp_mobile_sessions (stores JWT refresh tokens and FCM tokens) API Endpoints: - POST /twilio-mobile/v1/auth/login - POST /twilio-mobile/v1/auth/refresh - POST /twilio-mobile/v1/auth/logout - GET/POST /twilio-mobile/v1/agent/status - GET /twilio-mobile/v1/queues/state - POST /twilio-mobile/v1/calls/{call_sid}/accept - GET /twilio-mobile/v1/stream/events (SSE) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 15:43:14 -08:00
<?php
/**
* Automatic Plugin Updater
*
* Checks for updates from Gitea repository and installs them automatically
*/
class TWP_Auto_Updater {
private $plugin_slug = 'twilio-wp-plugin';
private $plugin_basename;
private $gitea_repo = 'wp-plugins/twilio-wp-plugin';
private $gitea_api_url;
private $current_version;
private $gitea_base_url = 'https://repo.anhonesthost.net';
/**
* Constructor
*/
public function __construct() {
$this->plugin_basename = plugin_basename(dirname(dirname(__FILE__)) . '/twilio-wp-plugin.php');
$this->current_version = defined('TWP_VERSION') ? TWP_VERSION : '0.0.0';
$this->gitea_api_url = $this->gitea_base_url . '/api/v1/repos/' . $this->gitea_repo . '/releases/latest';
}
/**
* Initialize updater hooks
*/
public function init() {
// Hook into WordPress update checks
add_filter('pre_set_site_transient_update_plugins', array($this, 'check_for_update'));
add_filter('plugins_api', array($this, 'plugin_info'), 10, 3);
// Add settings page for manual check
add_action('admin_init', array($this, 'register_settings'));
// Add update check to admin notices
if (get_option('twp_auto_update_enabled', '1') === '1') {
add_action('admin_init', array($this, 'maybe_auto_check_updates'));
}
}
/**
* Register auto-update settings
*/
public function register_settings() {
register_setting('twp_settings', 'twp_auto_update_enabled');
register_setting('twp_settings', 'twp_gitea_repo');
register_setting('twp_settings', 'twp_gitea_token'); // Optional for private repos
}
/**
* Check for updates periodically
*/
public function maybe_auto_check_updates() {
$last_check = get_option('twp_last_update_check', 0);
$check_interval = 12 * HOUR_IN_SECONDS; // Check every 12 hours
if (time() - $last_check > $check_interval) {
update_option('twp_last_update_check', time());
// Force WordPress to check for updates
wp_clean_plugins_cache();
}
}
/**
* Check for plugin updates
*/
public function check_for_update($transient) {
if (empty($transient->checked)) {
return $transient;
}
// Get Gitea repo from settings if available
$custom_repo = get_option('twp_gitea_repo', '');
if (!empty($custom_repo)) {
$this->gitea_repo = $custom_repo;
$this->gitea_api_url = $this->gitea_base_url . '/api/v1/repos/' . $this->gitea_repo . '/releases/latest';
}
$update_info = $this->get_latest_release();
if ($update_info && version_compare($this->current_version, $update_info->version, '<')) {
$plugin_data = array(
'id' => 'twilio-wp-plugin',
'slug' => $this->plugin_slug,
'plugin' => $this->plugin_basename,
'new_version' => $update_info->version,
'url' => $update_info->homepage,
'package' => $update_info->download_url,
'tested' => '6.8',
'requires' => '5.8',
'requires_php' => '7.4',
'icons' => array(),
'banners' => array(),
'compatibility' => new stdClass(),
);
$transient->response[$this->plugin_basename] = (object) $plugin_data;
error_log("TWP Auto-Updater: New version {$update_info->version} available (current: {$this->current_version})");
} else {
error_log("TWP Auto-Updater: No updates available (current: {$this->current_version})");
}
return $transient;
}
/**
* Get plugin information for update screen
*/
public function plugin_info($false, $action, $args) {
if ($action !== 'plugin_information') {
return $false;
}
if (!isset($args->slug) || $args->slug !== $this->plugin_slug) {
return $false;
}
$update_info = $this->get_latest_release();
if (!$update_info) {
return $false;
}
$plugin_info = new stdClass();
$plugin_info->name = 'Twilio WP Plugin';
$plugin_info->slug = $this->plugin_slug;
$plugin_info->version = $update_info->version;
$plugin_info->author = '<a href="https://cybercove.io/">Joshua Knapp</a>';
$plugin_info->homepage = $update_info->homepage;
$plugin_info->download_link = $update_info->download_url;
$plugin_info->requires = '5.8';
$plugin_info->tested = '6.8';
$plugin_info->requires_php = '7.4';
$plugin_info->last_updated = $update_info->release_date;
$plugin_info->downloaded = 10;
$plugin_info->sections = array(
'description' => '<p>Twilio WordPress Plugin for call management and mobile app support.</p>',
'changelog' => '<pre>' . esc_html($update_info->changelog) . '</pre>',
'installation' => '<p>Upload the plugin to your WordPress site and activate it.</p>'
);
return $plugin_info;
}
/**
* Get latest release information from Gitea
*/
private function get_latest_release() {
// Check cache first (1 hour)
$cache_key = 'twp_latest_release';
$cached = get_transient($cache_key);
if ($cached !== false) {
return $cached;
}
// Use cURL for Gitea API
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $this->gitea_api_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json'));
curl_setopt($ch, CURLOPT_USERAGENT, 'WordPress/Twilio-WP-Plugin-Updater');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
// Add Gitea token if configured (for private repos)
$gitea_token = get_option('twp_gitea_token', '');
if (!empty($gitea_token)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Accept: application/json',
'Authorization: token ' . $gitea_token
));
}
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (!$response || $http_code !== 200) {
error_log("TWP Auto-Updater: Gitea API returned status $http_code");
return false;
}
$release = json_decode($response);
if (!$release || !isset($release->tag_name)) {
error_log('TWP Auto-Updater: Invalid release data from Gitea');
return false;
}
// Parse release information
$version = ltrim($release->tag_name, 'v'); // Remove 'v' prefix if present
$download_url = null;
// Find the zip asset
if (isset($release->assets) && is_array($release->assets)) {
foreach ($release->assets as $asset) {
if (strpos($asset->name, '.zip') !== false) {
$download_url = $asset->browser_download_url;
break;
}
}
}
// Fallback to zipball if no asset found
if (!$download_url) {
$download_url = $release->zipball_url;
}
// Format changelog
$changelog = !empty($release->body) ? $release->body : 'No changelog provided for this release.';
// Handle empty changelog
if (empty(trim($changelog))) {
$changelog = "Version " . $version . "\n\n" .
"Released on " . date('F j, Y', strtotime($release->published_at)) . "\n\n" .
"* Updated plugin files";
}
$update_info = (object) array(
'version' => $version,
'download_url' => $download_url,
'homepage' => $this->gitea_base_url . '/' . $this->gitea_repo,
'release_date' => $release->published_at,
'description' => $changelog,
'changelog' => $changelog
);
// Cache for 1 hour
set_transient($cache_key, $update_info, HOUR_IN_SECONDS);
return $update_info;
}
/**
* Manual update check (for admin page)
*/
public function manual_check_for_updates() {
// Clear cache
delete_transient('twp_latest_release');
update_option('twp_last_update_check', 0);
// Force WordPress to check
wp_clean_plugins_cache();
delete_site_transient('update_plugins');
$update_info = $this->get_latest_release();
if (!$update_info) {
return array(
'success' => false,
'message' => 'Failed to check for updates. Please check your internet connection and Gitea repository settings.'
);
}
if (version_compare($this->current_version, $update_info->version, '<')) {
return array(
'success' => true,
'update_available' => true,
'current_version' => $this->current_version,
'latest_version' => $update_info->version,
'message' => "Update available: Version {$update_info->version}. Go to Plugins page to update."
);
} else {
return array(
'success' => true,
'update_available' => false,
'current_version' => $this->current_version,
'message' => 'You are running the latest version.'
);
}
}
/**
* Get current update status
*/
public function get_update_status() {
$update_info = $this->get_latest_release();
return array(
'current_version' => $this->current_version,
'latest_version' => $update_info ? $update_info->version : 'Unknown',
'update_available' => $update_info && version_compare($this->current_version, $update_info->version, '<'),
'last_check' => get_option('twp_last_update_check', 0),
'auto_update_enabled' => get_option('twp_auto_update_enabled', '1') === '1'
);
}
}