pluginSlug = $pluginSlug; $this->pluginVersion = $pluginVersion; $this->licenseKey = $licenseKey; $this->pluginFilePath = $this->pluginSlug . '/' . $this->pluginSlug . '.php'; } /** * Hooks to check for updates and add necessary filters and actions. */ public function handle() { add_filter('plugins_api', [$this, 'pluginsApiInfo'], 20, 3); add_filter('pre_set_site_transient_update_plugins', [$this, 'checkForUpdate']); add_action('upgrader_process_complete', [$this, 'clearCache'], 10, 2); } public function handleLicenseNotice() { add_action("after_plugin_row_{$this->pluginFilePath}", [$this, 'showLicenseNotice'], 10, 2); } /** * Handle the plugins_api call, returning version information when requested. * * @param mixed $res * @param string $action * @param object $args * @return mixed */ public function pluginsApiInfo($res, $action, $args) { if ($action !== 'plugin_information' || $this->pluginSlug !== $args->slug) { return $res; } $remote = $this->requestUpdateInfo(); if (!$remote) { return $res; } $res = new stdClass(); $res->name = $remote->name; $res->slug = $remote->slug; $res->version = $remote->version; $res->tested = $remote->tested; $res->requires = $remote->requires; $res->author = $remote->author; $res->author_profile = $remote->author_profile; $res->download_link = $remote->download_url; $res->requires_php = $remote->requires_php; $res->last_updated = $remote->last_updated; // Sections such as description, installation, changelog $res->sections = [ 'description' => $remote->sections->description, 'installation' => $remote->sections->installation, 'changelog' => $remote->sections->changelog, ]; $res->icons = [ '1x' => $remote->icons->low, '2x' => $remote->icons->high, ]; $res->banners = [ 'low' => $remote->banners->low, 'high' => $remote->banners->high, ]; return $res; } /** * Fetch the version information from the API using ApiCommunicator and handle exceptions. * * @return object|false */ private function requestUpdateInfo() { // Don't request update info if the license key is not provided if (empty($this->licenseKey)) { // If license is empty, force a check for updates by removing update_plugins transient delete_site_transient('update_plugins'); return false; } try { $apiCommunicator = new ApiCommunicator(); $remote = $apiCommunicator->getDownloadUrl($this->licenseKey, $this->pluginSlug); if (!$remote) { throw new Exception('Failed to retrieve remote plugin information.'); } if (isset($remote->code) && isset($remote->message)) { throw new Exception($remote->message, $remote->code); } /** * Adjusts the tested version to ignore the patch number for compatibility checks. * Based on the patch from https://core.trac.wordpress.org/ticket/62151. * * @note If the patch is applied in WordPress core, this section can be removed. */ if (isset($remote->tested)) { $remote->tested = $this->adjustPatchVersion($remote->tested); } return $remote; } catch (Exception $e) { WP_Statistics::log($e->getMessage(), 'error'); return false; } } /** * Check if an update is available by comparing versions. * * @param object $transient * @return object */ public function checkForUpdate($transient) { if (empty($transient->checked)) { return $transient; } $remote = $this->requestUpdateInfo(); if ($remote) { $res = new stdClass(); $res->slug = $this->pluginSlug; $res->plugin = $this->pluginFilePath; $res->new_version = $remote->version; $res->tested = $remote->tested; $res->package = $remote->download_url; $res->icons = [ '1x' => $remote->icons->low, '2x' => $remote->icons->high, ]; $res->banners = [ 'low' => $remote->banners->low, 'high' => $remote->banners->high, ]; if (version_compare($this->pluginVersion, $remote->version, '<')) { $transient->response[$res->plugin] = $res; } else { $transient->no_update[$res->plugin] = $res; } } return $transient; } /** * Show a notice if the license key is missing or the update request fails. * * @param string $pluginFile * @param array $pluginData */ public function showLicenseNotice($pluginFile, $pluginData) { // Check if the license key is missing or the request failed if (!$this->requestUpdateInfo()) { // Get the columns for this table so we can calculate the colspan attribute. $screen = get_current_screen(); $columns = get_column_headers($screen); // If something went wrong with retrieving the columns, default to 3 for colspan. $colspan = !is_countable($columns) ? 3 : count($columns); $isActive = is_plugin_active($this->pluginFilePath); // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped ?>
%s.', $this->pluginSlug), esc_attr($pluginData['Name'])); ?> activate your license.', $this->pluginSlug), Menus::admin_url('plugins', ['tab' => 'add-license'])); ?>