270 lines
8.2 KiB
PHP
270 lines
8.2 KiB
PHP
<?php
|
|
/**
|
|
* Plugin Updater
|
|
*
|
|
* Handles automatic updates from IGNY8 API
|
|
*
|
|
* @package Igny8Bridge
|
|
*/
|
|
|
|
// Prevent direct access
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
class Igny8_Updater {
|
|
|
|
/**
|
|
* Plugin slug
|
|
*
|
|
* @var string
|
|
*/
|
|
private $plugin_slug = 'igny8-wp-bridge';
|
|
|
|
/**
|
|
* Plugin file
|
|
*
|
|
* @var string
|
|
*/
|
|
private $plugin_file;
|
|
|
|
/**
|
|
* Current version
|
|
*
|
|
* @var string
|
|
*/
|
|
private $version;
|
|
|
|
/**
|
|
* API URL
|
|
*
|
|
* @var string
|
|
*/
|
|
private $api_url;
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param string $plugin_file Plugin file path
|
|
* @param string $version Current version
|
|
* @param string $api_url API URL
|
|
*/
|
|
public function __construct($plugin_file, $version, $api_url) {
|
|
$this->plugin_file = $plugin_file;
|
|
$this->version = $version;
|
|
$this->api_url = trailingslashit($api_url);
|
|
|
|
// Hook into WordPress update system
|
|
add_filter('pre_set_site_transient_update_plugins', array($this, 'check_for_updates'));
|
|
add_filter('plugins_api', array($this, 'plugin_info'), 10, 3);
|
|
|
|
// Clear update cache after plugin is updated
|
|
add_action('upgrader_process_complete', array($this, 'clear_update_cache'), 10, 2);
|
|
|
|
// Add custom styling for plugin details popup
|
|
add_action('admin_enqueue_scripts', array($this, 'enqueue_plugin_details_styles'));
|
|
}
|
|
|
|
/**
|
|
* Check for plugin updates
|
|
*
|
|
* @param object $transient Update transient
|
|
* @return object Modified transient
|
|
*/
|
|
public function check_for_updates($transient) {
|
|
if (empty($transient->checked)) {
|
|
return $transient;
|
|
}
|
|
|
|
// Get update info from IGNY8 API
|
|
$update_info = $this->get_update_info();
|
|
|
|
if (!$update_info || !isset($update_info['latest_version'])) {
|
|
return $transient;
|
|
}
|
|
|
|
$plugin_basename = plugin_basename($this->plugin_file);
|
|
$latest_version = $update_info['latest_version'];
|
|
|
|
// Only show update if latest version is actually newer than current
|
|
if (version_compare($this->version, $latest_version, '<')) {
|
|
$transient->response[$plugin_basename] = (object) array(
|
|
'slug' => $this->plugin_slug,
|
|
'new_version' => $latest_version,
|
|
'package' => $update_info['download_url'] ?? '',
|
|
'url' => $update_info['info_url'] ?? '',
|
|
'tested' => $update_info['tested'] ?? '',
|
|
'requires_php' => $update_info['requires_php'] ?? '',
|
|
);
|
|
} else {
|
|
// CRITICAL FIX: Explicitly mark as no update by removing from response
|
|
// and adding to no_update to prevent false update notifications
|
|
if (isset($transient->response[$plugin_basename])) {
|
|
unset($transient->response[$plugin_basename]);
|
|
}
|
|
|
|
// Mark plugin as checked with no update available
|
|
if (!isset($transient->no_update)) {
|
|
$transient->no_update = array();
|
|
}
|
|
|
|
$transient->no_update[$plugin_basename] = (object) array(
|
|
'slug' => $this->plugin_slug,
|
|
'plugin' => $plugin_basename,
|
|
'new_version' => $this->version,
|
|
'url' => $update_info['info_url'] ?? '',
|
|
'package' => '',
|
|
);
|
|
}
|
|
|
|
return $transient;
|
|
}
|
|
|
|
/**
|
|
* Provide plugin information for update screen
|
|
*
|
|
* @param false|object|array $result The result object or array
|
|
* @param string $action The type of information being requested
|
|
* @param object $args Plugin API arguments
|
|
* @return false|object Modified result
|
|
*/
|
|
public function plugin_info($result, $action, $args) {
|
|
if ($action !== 'plugin_information') {
|
|
return $result;
|
|
}
|
|
|
|
if (!isset($args->slug) || $args->slug !== $this->plugin_slug) {
|
|
return $result;
|
|
}
|
|
|
|
// Get plugin info from IGNY8 API
|
|
$info = $this->get_plugin_info();
|
|
|
|
if (!$info) {
|
|
return $result;
|
|
}
|
|
|
|
return (object) array(
|
|
'name' => $info['name'] ?? 'IGNY8 WordPress Bridge',
|
|
'slug' => $this->plugin_slug,
|
|
'version' => $info['version'] ?? $this->version,
|
|
'author' => '<a href="https://igny8.com">IGNY8</a>',
|
|
'author_profile' => 'https://igny8.com',
|
|
'homepage' => 'https://igny8.com',
|
|
'sections' => array(
|
|
'description' => $info['description'] ?? '',
|
|
'changelog' => $info['changelog'] ?? '',
|
|
),
|
|
'download_link' => $info['download_url'] ?? '',
|
|
'tested' => $info['tested'] ?? '',
|
|
'requires_php' => $info['requires_php'] ?? '7.4',
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Clear update cache after plugin update completes
|
|
*
|
|
* Fixes the double-update notification bug by forcing WordPress
|
|
* to re-check for updates with the new version number
|
|
*
|
|
* @param WP_Upgrader $upgrader WP_Upgrader instance
|
|
* @param array $hook_extra Extra arguments passed to hooked filters
|
|
*/
|
|
public function clear_update_cache($upgrader, $hook_extra) {
|
|
// Check if this is a plugin update
|
|
if (!isset($hook_extra['type']) || $hook_extra['type'] !== 'plugin') {
|
|
return;
|
|
}
|
|
|
|
// Check if our plugin was updated
|
|
$plugin_basename = plugin_basename($this->plugin_file);
|
|
$updated_plugins = array();
|
|
|
|
if (isset($hook_extra['plugin'])) {
|
|
$updated_plugins[] = $hook_extra['plugin'];
|
|
} elseif (isset($hook_extra['plugins'])) {
|
|
$updated_plugins = $hook_extra['plugins'];
|
|
}
|
|
|
|
// If our plugin was updated, force WordPress to recheck updates
|
|
if (in_array($plugin_basename, $updated_plugins, true)) {
|
|
// Delete the update_plugins transient to force a fresh check
|
|
delete_site_transient('update_plugins');
|
|
|
|
// Also clear any cached update info
|
|
wp_cache_delete('igny8_update_check', 'igny8');
|
|
|
|
// Log the cache clear for debugging
|
|
error_log('IGNY8: Cleared update cache after plugin update to version ' . $this->version);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Enqueue custom styles for plugin details popup
|
|
*/
|
|
public function enqueue_plugin_details_styles() {
|
|
// No custom styles needed
|
|
}
|
|
|
|
/**
|
|
* Get update information from IGNY8 API
|
|
*
|
|
* @return array|false Update info or false on failure
|
|
*/
|
|
private function get_update_info() {
|
|
$url = $this->api_url . $this->plugin_slug . '/check-update/';
|
|
|
|
$response = wp_remote_get($url, array(
|
|
'timeout' => 10,
|
|
'headers' => array(
|
|
'X-IGNY8-Site-ID' => get_option('igny8_site_id'),
|
|
'X-IGNY8-API-Key' => get_option('igny8_api_key'),
|
|
),
|
|
'body' => array(
|
|
'current_version' => $this->version,
|
|
),
|
|
));
|
|
|
|
if (is_wp_error($response)) {
|
|
return false;
|
|
}
|
|
|
|
$code = wp_remote_retrieve_response_code($response);
|
|
if ($code !== 200) {
|
|
return false;
|
|
}
|
|
|
|
$body = wp_remote_retrieve_body($response);
|
|
$data = json_decode($body, true);
|
|
|
|
return $data ?: false;
|
|
}
|
|
|
|
/**
|
|
* Get plugin information from IGNY8 API
|
|
*
|
|
* @return array|false Plugin info or false on failure
|
|
*/
|
|
private function get_plugin_info() {
|
|
$url = $this->api_url . $this->plugin_slug . '/info/';
|
|
|
|
$response = wp_remote_get($url, array(
|
|
'timeout' => 10,
|
|
));
|
|
|
|
if (is_wp_error($response)) {
|
|
return false;
|
|
}
|
|
|
|
$code = wp_remote_retrieve_response_code($response);
|
|
if ($code !== 200) {
|
|
return false;
|
|
}
|
|
|
|
$body = wp_remote_retrieve_body($response);
|
|
$data = json_decode($body, true);
|
|
|
|
return $data ?: false;
|
|
}
|
|
}
|