HEX
Server: Apache
System: Linux nc-ph-4101.simplemoneygoals.com 5.14.0-503.21.1.el9_5.x86_64 #1 SMP PREEMPT_DYNAMIC Sun Jan 12 09:45:05 EST 2025 x86_64
User: dailygoldindex (1004)
PHP: 8.1.33
Disabled: NONE
Upload Files
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);
    }
}