File: /home/dailygoldindex/public_html/wp-content/plugins/toolkit/utils/update.php
<?php
declare(strict_types=1);
/**
* Update WordPress plugin from GitHub Private Repository.
*/
class ToolkitGhPluginUpdater
{
private $file;
private $plugin_data;
private $basename;
private $active = false;
private $github_response;
public function __construct($file)
{
$this->file = $file;
$this->basename = plugin_basename($this->file);
}
/**
* Init GitHub Plugin Updater.
*/
public function init(): void
{
add_filter('pre_set_site_transient_update_plugins', [$this, 'modify_transient'], 10, 1);
add_filter('http_request_args', [$this, 'set_header_token'], 10, 2);
add_filter('plugins_api', [$this, 'plugin_popup'], 10, 3);
add_filter('upgrader_post_install', [$this, 'after_install'], 10, 3);
register_activation_hook($this->file, [$this, 'custom_plugin_activation']);
}
public function custom_plugin_activation(): void
{
ob_start();
try {
$this->get_repository_info();
$this->get_plugin_data();
$zip_file = $this->download_asset_to_tmp($this->github_response['assets'][0]['url'], $this->github_response['tag_name']);
$plugin_info = [
'url' => 'https://github.com/epc-wordpress/toolkit',
'slug' => current(explode('/', $this->basename)),
'package' => $zip_file, // Local file path
'new_version' => $this->github_response['tag_name'],
];
$transient = get_site_transient('update_plugins');
if (!is_object($transient)) {
$transient = (object) ['response' => []];
}
$transient->response[$plugin_slug] = (object) $plugin_info;
set_site_transient('update_plugins', $transient);
} catch (Exception $e) {
error_log('Error during plugin activation: ' . $e->getMessage());
}
ob_end_clean();
}
/**
* If new version exists, update transient with GitHub info.
*
* @param object $transient Transient object with plugins information.
*/
public function modify_transient(object $transient): object
{
if (! property_exists($transient, 'checked')) {
return $transient;
}
$this->get_repository_info();
$this->get_plugin_data();
if (version_compare($this->github_response['tag_name'], $transient->checked[$this->basename], 'gt')) {
// Download the release zip file to tmp directory
$zip_file = $this->download_asset_to_tmp($this->github_response['assets'][0]['url'], $this->github_response['tag_name']);
// Update transient to point to local zip file in tmp directory
$plugin = [
'url' => $this->plugin_data['PluginURI'],
'slug' => current(explode('/', $this->basename)),
'package' => $zip_file, // Local file path
'new_version' => $this->github_response['tag_name'],
];
$transient->response[$this->basename] = (object) $plugin;
} else{
$zip_file = $this->download_asset_to_tmp($this->github_response['assets'][0]['url'], $this->github_response['tag_name']);
$plugin = [
'url' => 'https://github.com/epc-wordpress/toolkit',
'slug' => current(explode('/', $this->basename)),
'package' => $zip_file, // Local file path
'new_version' => $this->github_response['tag_name'],
];
$transient->no_update[$this->basename] = (object) $plugin;
}
return $transient;
}
/**
* Download GitHub release to tmp directory.
*
* @param string $zip_url The GitHub zipball URL.
* @return string Path to the downloaded zip file.
*/
private function download_asset_to_tmp(string $assetUrl, string $version): string
{
$tmp_dir = plugin_dir_path($this->file) . 'tmp/';
if (!is_dir($tmp_dir)) {
mkdir($tmp_dir, 0755, true);
}
$zip_path = $tmp_dir . "toolkit-{$version}.zip";
if (file_exists($zip_path)) {
$this->cleanup_old_files($tmp_dir);
return $zip_path;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $assetUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer " . GHPU_AUTH_TOKEN,
"Accept: application/octet-stream",
"X-GitHub-Api-Version: 2022-11-28",
"User-Agent: MyApp"
]);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
$fp = fopen($zip_path, 'wb');
if ($fp === false) {
throw new Exception("Unable to open file for writing: $zip_path");
}
curl_setopt($ch, CURLOPT_FILE, $fp);
$response = curl_exec($ch);
if ($response === false) {
fclose($fp);
curl_close($ch);
throw new Exception("Error downloading file: " . curl_error($ch));
}
fclose($fp);
curl_close($ch);
$this->cleanup_old_files($tmp_dir);
return $zip_path;
}
/**
* Delete old archives.
*/
private function cleanup_old_files(string $tmp_dir): void
{
$files = glob($tmp_dir . 'toolkit-*.zip');
if (count($files) <= 2) {
return;
}
usort($files, function ($a, $b) {
return filemtime($a) <=> filemtime($b);
});
foreach (array_slice($files, 0, -2) as $old_file) {
unlink($old_file);
}
}
/**
* Complete details of new plugin version on popup.
*
* @param array|false|object $result The result object or array. Default false.
* @param string $action The type of information being requested from the Plugin Installation API.
* @param object $args Plugin API arguments.
*/
public function plugin_popup(bool $result, string $action, object $args)
{
if ('plugin_information' !== $action || empty($args->slug)) {
return false;
}
if ($args->slug == current(explode('/', $this->basename))) {
$this->get_repository_info();
$this->get_plugin_data();
$plugin = [
'name' => $this->plugin_data['Name'],
'slug' => $this->basename,
'requires' => $this->plugin_data['RequiresWP'],
'version' => $this->github_response['tag_name'],
'author' => $this->plugin_data['AuthorName'],
'author_profile' => $this->plugin_data['AuthorURI'],
'last_updated' => $this->github_response['published_at'],
'homepage' => $this->plugin_data['PluginURI'],
'short_description' => $this->plugin_data['Description'],
'sections' => [
'Description' => $this->plugin_data['Description'],
'Updates' => $this->github_response['body'],
],
'download_link' => plugin_dir_path($this->file) . 'tmp/latest.zip',
];
return (object) $plugin;
}
return $result;
}
/**
* Active plugin after install new version.
*
* @param bool $response Installation response.
* @param array $hook_extra Extra arguments passed to hooked filters.
* @param array $result Installation result data.
*/
public function after_install(bool $response, array $hook_extra, array $result): bool
{
global $wp_filesystem;
$install_directory = plugin_dir_path($this->file);
$wp_filesystem->move($result['destination'], $install_directory);
$result['destination'] = $install_directory;
if ($this->active) {
activate_plugin($this->basename);
}
return $response;
}
/**
* GitHub access_token param was deprecated. We need to set header with token for requests.
*
* @param array $args HTTP request arguments.
* @param string $url The request URL.
*/
public function set_header_token(array $parsed_args, string $url): array
{
$parsed_url = parse_url($url);
if ('api.github.com' === ($parsed_url['host'] ?? null) && isset($parsed_url['query'])) {
parse_str($parsed_url['query'], $query);
if (isset($query['access_token'])) {
$parsed_args['headers']['Authorization'] = 'Bearer ' . $query['access_token'];
$this->active = is_plugin_active($this->basename);
}
}
if (strpos($url, 'zipball') !== false) {
if (defined('GHPU_AUTH_TOKEN')) {
$parsed_args['headers']['Authorization'] = 'Bearer ' . GHPU_AUTH_TOKEN;
}
}
return $parsed_args;
}
/**
* Gets repository data from GitHub.
*/
private function get_repository_info(): void
{
if (null !== $this->github_response) {
return;
}
$args = [
'method' => 'GET',
'timeout' => 5,
'redirection' => 5,
'httpversion' => '1.0',
'headers' => [
'Authorization' => 'Bearer ' . GHPU_AUTH_TOKEN,
],
'sslverify' => true,
];
$request_uri = sprintf(GH_REQUEST_URI, GHPU_USERNAME, GHPU_REPOSITORY);
$request = wp_remote_get($request_uri, $args);
$response = json_decode(wp_remote_retrieve_body($request), true);
if (is_array($response)) {
$response = current($response);
}
$this->github_response = $response;
}
/**
* Gets plugin data.
*/
private function get_plugin_data(): void
{
if (null !== $this->plugin_data) {
return;
}
$this->plugin_data = get_plugin_data($this->file);
}
}