HEX
Server: LiteSpeed
System: Linux pulsar191.sitesanctuary.org 5.14.0-284.30.1.el9.tuxcare.els9.x86_64 #1 SMP PREEMPT_DYNAMIC Fri Jan 10 17:34:05 UTC 2025 x86_64
User: lgooir (1604)
PHP: 8.1.32
Disabled: exec,system,passthru,shell_exec,escapeshellarg,escapeshellcmd,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Upload Files
File: /home/lgooir/.trash/rising-bamboo/inc/app/admin/class-update.php
<?php
/**
 * RisingBambooCore.
 *
 * @package RisingBambooCore
 */

namespace RisingBambooCore\App\Admin;

use JsonException;
use RisingBambooCore\App\App;
use RisingBambooCore\Core\Singleton;
use RisingBambooCore\Helper\License;
use RisingBambooCore\Helper\Setting;
use RisingBambooCore\Helper\Theme;
use stdClass;

/**
 * Check update RisingBamboo Plg and Theme.
 */
class Update extends Singleton {

	/**
	 * API URL.
	 *
	 * @var string|mixed|null
	 */
	protected string $api_url;

	/**
	 * ID of Plg on API.
	 *
	 * @var string|mixed|null
	 */
	protected string $plugin_id;

	/**
	 * Plugin Slug.
	 *
	 * @var string
	 */
	protected string $plugin_slug;

	/**
	 * Plugin Data.
	 *
	 * @var false|mixed
	 */
	protected $plugin_data;

	/**
	 * All RBB Theme.
	 *
	 * @var array
	 */
	protected array $themes = [];


	/**
	 * Cache allow.
	 *
	 * @var bool
	 */
	protected bool $cache_allowed;

	/**
	 * Cache Key.
	 *
	 * @var string
	 */
	protected string $plugin_cache_key;

	/**
	 * Cache Key.
	 *
	 * @var string
	 */
	protected string $theme_cache_key;

	/**
	 * The account to which the product belongs.
	 *
	 * @var string|mixed|null
	 */
	protected string $market_account;

	/**
	 * Construct.
	 */
	public function __construct() {
		if ( is_admin() ) {
			$this->api_url = App::get_info('api');
			if ( Setting::get_option('development_mode') ) {
				$this->cache_allowed = false;
			} else {
				$this->cache_allowed = true;
			}
			$this->init_plugin_data();

			$this->init_theme_data();

			add_filter('plugin_row_meta', [ $this, 'plugin_row_meta' ], 10, 3);
			add_filter('plugins_api', [ $this, 'info' ], 10, 3);
			add_filter('pre_set_site_transient_update_plugins', [ $this, 'plugin_update' ]);
			add_filter('pre_set_site_transient_update_themes', [ $this, 'theme_update' ]);
			add_filter('http_request_args', [ $this, 'allow_http_update' ], 999);

			add_action('upgrader_process_complete', [ $this, 'purge' ], 10, 2);

			$this->force_update_check();
		}
	}

	/**
	 * Init Plugin Data.
	 *
	 * @return void
	 * @throws JsonException Throw Error.
	 */
	public function init_plugin_data(): void {
		$this->plugin_id      = App::get_info('id');
		$this->market_account = App::get_info('account');

		$this->plugin_slug = dirname(RBB_CORE_BASENAME);

		$this->plugin_cache_key = strtolower('plg-' . $this->plugin_slug . '-update');

		$this->plugin_data = $this->request(
			[
				'id'      => $this->plugin_id,
				'account' => $this->market_account,
			],
			$this->plugin_cache_key
		);
	}

	/**
	 * Init Theme Data.
	 *
	 * @return void
	 * @throws JsonException Throw Error.
	 */
	public function init_theme_data(): void {
		$themes = Theme::instance()->get_themes();
		foreach ( $themes as $stylesheet => $theme ) {
			$license = License::is_activated($stylesheet);
			if ( $license ) {
				$this->theme_cache_key                   = strtolower('rbb-theme-' . $stylesheet . '-update');
				$this->themes[ $stylesheet ] ['version'] = $theme->get('Version');
				$this->themes[ $stylesheet ] ['update']  = $this->request(
					[
						'token' => $license['token'],
					],
					$this->theme_cache_key
				);
			}
		}
	}

	/**
	 * Info.
	 *
	 * @param mixed $result Result.
	 * @param mixed $action Action.
	 * @param mixed $args Args.
	 * @return mixed
	 */
	public function info( $result, $action, $args ) {
		$data = $this->plugin_data;
		if ( 'plugin_information' !== $action || $this->plugin_slug !== $args->slug || ! $data ) {
			return $result;
		}

		$result = new stdClass();

		$result->name           = $data->name;
		$result->slug           = $data->slug;
		$result->version        = $data->version;
		$result->tested         = $data->tested;
		$result->requires       = $data->requires;
		$result->author         = $data->author;
		$result->author_profile = $data->author_profile;
		$result->download_link  = $data->download_url;
		$result->trunk          = $data->download_url;
		$result->requires_php   = $data->requires_php;
		$result->last_updated   = $data->last_updated;

		$result->sections = [
			'description'  => nl2br($data->sections->description),
			'installation' => nl2br($data->sections->installation),
			'changelog'    => nl2br($data->sections->changelog),
		];

		if ( ! empty($data->banners) ) {
			$result->banners = [
				'low'  => $data->banners->low,
				'high' => $data->banners->high,
			];
		}
		return $result;
	}

	/**
	 * Get Request.
	 *
	 * @param array  $params The Params.
	 * @param string $cache The Cache Key.
	 * @return false|mixed
	 * @throws JsonException Exception.
	 */
	public function request( array $params, string $cache ) {

		$data = get_transient($cache);

		if ( false === $data || ! $this->cache_allowed ) {
			$url    = $this->api_url . '/update/check';
			$remote = wp_remote_get(
				$url,
				[
					'timeout' => 10,
					'headers' => [
						'Accept' => 'application/json',
					],
					'body'    => $params,
				]
			);
            //phpcs:ignore
			if ( is_wp_error($remote) || 200 !== wp_remote_retrieve_response_code($remote) || empty($response = wp_remote_retrieve_body($remote)) ) {
				return false;
			}
// 			$data    = json_decode($response, false, 512, JSON_THROW_ON_ERROR);
			$data    = $data->data;
			$expired = $data->download_url_expired ?? HOUR_IN_SECONDS;
			set_transient($cache, $data, $expired);
		}
		return $data;
	}

	/**
	 * Update.
	 *
	 * @param mixed $transient Transient.
	 * @return mixed
	 * @throws JsonException Exception.
	 */
	public function plugin_update( $transient ) {
		if ( ! empty($transient->checked) ) {
			$data = $this->plugin_data;
			if ( $this->can_update($data, untrailingslashit(App::get_info('Version'))) ) {
				$result              = new stdClass();
				$result->slug        = $this->plugin_slug;
				$result->plugin      = plugin_basename(RBB_CORE_PATH_FILE);
				$result->new_version = $data->version;
				$result->tested      = $data->tested;
				$result->package     = $data->download_url;
				$result->banners     = json_decode(wp_json_encode($data->banners, JSON_THROW_ON_ERROR), true, 512, JSON_THROW_ON_ERROR);
				$result->icons       = json_decode(wp_json_encode($data->icons, JSON_THROW_ON_ERROR), true, 512, JSON_THROW_ON_ERROR);

				$transient->response[ $result->plugin ] = $result;
			}
		}
		return $transient;
	}

	/**
	 * Update Theme.
	 *
	 * @param mixed $transient Transient.
	 * @return mixed
	 */
	public function theme_update( $transient ) {
		if ( ! empty($transient->checked) && $this->themes ) {
			foreach ( $this->themes as $slug => $theme ) {
				$update  = $theme['update'];
				$version = $theme['version'];
				if ( $this->can_update($update, $version) ) {
					$result                = [];
					$result['url']         = $update->url;
					$result['slug']        = $update->slug;
					$result['new_version'] = $update->version;
					$result['tested']      = $update->tested;
					$result['package']     = $update->download_url;

					$transient->response[ $slug ] = $result;
				}
			}
		}
		return $transient;
	}

	/**
	 * Pure.
	 *
	 * @param mixed $upgrader Upgrader.
	 * @param mixed $options Options.
	 * @return void
	 */
	public function purge( $upgrader, $options ): void {

		if ( $this->cache_allowed && 'update' === $options['action'] ) {
			if ( 'plugin' === $options['type'] ) {
				delete_transient($this->plugin_cache_key);
			}
			if ( 'theme' === $options['type'] ) {
				delete_transient($this->theme_cache_key);
			}
		}
	}

	/**
	 * Add Plugin Meta Link.
	 *
	 * @param mixed $plugin_meta Meta.
	 * @param mixed $plugin_file File.
	 * @param mixed $plugin_data Data.
	 * @return mixed
	 */
	public function plugin_row_meta( $plugin_meta, $plugin_file, $plugin_data ) {
		if ( RBB_CORE_PATH_FILE === path_join(WP_PLUGIN_DIR, $plugin_file) ) {
			/* translators: %s: link */
			$plugin_meta[] = sprintf(
				'<a target="_blank" href="%s" aria-label="%s" data-title="%s">%s</a>',
				esc_url(App::get_info('docs')),
				/* translators: %s: link */
				esc_attr(sprintf(__('More information about %s', App::get_domain()), $plugin_data['Name'])),
				esc_attr($plugin_data['Name']),
				__('Docs', App::get_domain())
			);
		}
		return $plugin_meta;
	}

	/**
	 * Allow http when updating.
	 *
	 * @param mixed $args Args.
	 * @return mixed
	 */
	public function allow_http_update( $args ) {
        //phpcs:ignore
		if ( $this->plugin_data && $url = $this->plugin_data->download_url ) {
			$url = wp_parse_url($url, PHP_URL_SCHEME);
			if ( 'http' === $url ) {
				$args['reject_unsafe_urls'] = false;
			}
		}
		return $args;
	}

	/**
	 * Check update
	 *
	 * @param mixed  $data Data.
	 * @param string $version Version.
	 * @return bool
	 */
	public function can_update( $data, string $version ): bool {
		return $data && version_compare($data->requires_php, PHP_VERSION, '<') && version_compare($version, $data->version, '<') && version_compare($data->requires, get_bloginfo('version'), '<=');
	}

	/**
	 * Force WordPress check the update.
	 *
	 * @return void
	 */
	protected function force_update_check(): void {
		/**
		 * When enable this func, button Update Now at detail plugin will disappear.
		 */
		if ( Setting::get_option('development_mode') ) {
			set_site_transient('update_plugins', null);
			set_site_transient('update_themes', null);
		}
	}
}