file = $file; $this->option_prefix = 'siti_updater_' . sanitize_key(dirname(plugin_basename($this->file))) . '_'; $this->set_plugin_properties(); // Register this instance globally self::$instances[$this->option_prefix] = $this; add_action('admin_init', array($this, 'set_plugin_properties')); add_action('admin_notices', array($this, 'admin_notices')); add_action('siti_updater_daily_check_' . $this->option_prefix, array($this, 'daily_license_check')); if (!wp_next_scheduled('siti_updater_daily_check_' . $this->option_prefix)) { wp_schedule_event(time(), 'daily', 'siti_updater_daily_check_' . $this->option_prefix); } return $this; } public function initialize() { add_filter('pre_set_site_transient_update_plugins', array($this, 'check_for_updates')); add_filter('plugins_api', array($this, 'plugin_info'), 10, 3); // Register global settings page only once if (!self::$global_settings_registered) { add_action('admin_menu', array($this, 'add_global_settings_page')); self::$global_settings_registered = true; } } public function set_plugin_properties() { if (!function_exists('get_plugin_data')) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $this->plugin = get_plugin_data($this->file, false, false); $this->basename = plugin_basename($this->file); $this->active = is_plugin_active($this->basename); } public static function get_instances() { return self::$instances; } public function get_plugin_data() { return $this->plugin; } public function set_owner($owner) { $this->owner = $owner; } public function set_repository($repository) { $this->repository = $repository; } public function set_license_key($key) { $sanitized_key = sanitize_text_field((string) $key); $stored_key = get_option($this->option_prefix . 'license_key', ''); if ($stored_key !== $sanitized_key) { $this->clear_cached_license_data(); } $this->license_key = $sanitized_key; update_option($this->option_prefix . 'license_key', $sanitized_key); } public function get_license_key() { if (null === $this->license_key) { $this->license_key = get_option($this->option_prefix . 'license_key', ''); } return $this->license_key; } public function get_license_data() { return $this->get_stored_license_data(); } public function set_api_base_url($api_base_url) { $this->api_base_url = rtrim((string) $api_base_url, '/'); } private function normalize_version($version) { if (!is_string($version)) { return $version; } $version = trim($version); if ('' === $version) { return $version; } if (0 === stripos($version, 'v')) { $version = ltrim($version, 'vV'); } return $version; } private function get_stored_license_data() { $data = get_option($this->option_prefix . 'license_data', array()); return is_array($data) ? $data : array(); } private function clear_cached_license_data() { delete_option($this->option_prefix . 'license_data'); delete_option($this->option_prefix . 'last_check'); } private function store_license_data($body) { if (!is_array($body)) { $body = array(); } $license_data = array(); if (isset($body['license']) && is_array($body['license'])) { $license_data = $body['license']; } if (empty($license_data['key'])) { $license_data['key'] = $this->get_license_key(); } $license_data['licenseValid'] = !empty($body['valid']); $version = null; if (isset($body['pluginVersion']) && $body['pluginVersion']) { $version = $body['pluginVersion']; } elseif (isset($body['version']) && $body['version']) { $version = $body['version']; } elseif (isset($license_data['pluginVersion']) && $license_data['pluginVersion']) { $version = $license_data['pluginVersion']; } if ($version) { $license_data['pluginVersion'] = $this->normalize_version($version); } update_option($this->option_prefix . 'license_data', $license_data); update_option($this->option_prefix . 'last_check', current_time('mysql')); } private function get_plugin_info() { if (is_null($this->plugin_response)) { $request_uri = sprintf('%s/api/plugins/%s/%s', $this->api_base_url, $this->owner, $this->repository); $response = wp_remote_get($request_uri, array('timeout' => 15)); if (is_wp_error($response)) { $this->plugin_response = false; return; } $code = wp_remote_retrieve_response_code($response); if (200 !== $code) { $this->plugin_response = false; return; } $body = json_decode(wp_remote_retrieve_body($response), true); if (is_array($body) && isset($body['version'])) { $body['version'] = $this->normalize_version($body['version']); } $this->plugin_response = $body; } } public function check_for_updates($transient) { if (empty($transient->checked)) { return $transient; } $this->get_plugin_info(); if (false === $this->plugin_response || empty($this->plugin_response['version'])) { return $transient; } $remote_version = $this->normalize_version($this->plugin_response['version']); $current_version = $this->normalize_version($this->plugin['Version']); if ($remote_version && version_compare($remote_version, $current_version, '>')) { $download_url = $this->get_download_url('latest'); if (!is_wp_error($download_url)) { $transient->response[$this->basename] = (object) array( 'slug' => dirname($this->basename), 'new_version' => $remote_version, 'package' => $download_url, 'tested' => get_bloginfo('version'), 'url' => $this->plugin_response['homepage'] ?? '', ); } } return $transient; } public function plugin_info($result, $action, $args) { if ('plugin_information' !== $action || $args->slug !== dirname($this->basename)) { return $result; } $this->get_plugin_info(); if (false === $this->plugin_response) { return $result; } return (object) array( 'name' => $this->plugin_response['name'] ?? $this->plugin['Name'], 'slug' => $args->slug, 'version' => $this->normalize_version($this->plugin_response['version'] ?? $this->plugin['Version']), 'author' => $this->plugin_response['author'] ?? $this->plugin['Author'], 'author_profile' => $this->plugin_response['author_url'] ?? $this->plugin['AuthorURI'], 'homepage' => $this->plugin_response['homepage'] ?? '', 'requires' => $this->plugin_response['requires'] ?? '', 'tested' => $this->plugin_response['tested'] ?? get_bloginfo('version'), 'downloaded' => $this->plugin_response['downloads'] ?? 0, 'last_updated' => $this->plugin_response['last_updated'] ?? '', 'sections' => array( 'description' => $this->plugin_response['description'] ?? $this->plugin['Description'], 'changelog' => $this->plugin_response['changelog'] ?? '', ), 'download_link' => $this->get_download_url('latest'), ); } private function get_download_url($version = 'latest') { $license_key = $this->get_license_key(); if (empty($license_key)) { return new WP_Error('no_license', 'Geen licentie ingesteld'); } $hostname = parse_url(home_url(), PHP_URL_HOST); return $this->api_base_url . '/api/licenses/download?key=' . urlencode($license_key) . '&hostname=' . urlencode($hostname) . '&version=' . urlencode($version); } public function verify_license() { $license_key = $this->get_license_key(); if (empty($license_key)) { return new WP_Error('missing_license', 'Geen licentiecode ingesteld.'); } $hostname = parse_url(home_url(), PHP_URL_HOST); $current_version = isset($this->plugin['Version']) ? $this->plugin['Version'] : null; $response = wp_remote_post($this->api_base_url . '/api/licenses/verify', array( 'headers' => array( 'Content-Type' => 'application/json', ), 'body' => wp_json_encode(array( 'key' => $license_key, 'hostname' => $hostname, 'currentVersion' => $current_version, 'owner' => $this->owner, 'repository' => $this->repository, )), 'timeout' => 15, )); if (is_wp_error($response)) { return $response; } $code = wp_remote_retrieve_response_code($response); $body = json_decode(wp_remote_retrieve_body($response), true); if (!is_array($body)) { $this->clear_cached_license_data(); return new WP_Error('verification_failed', 'Onverwacht antwoord van licentieserver.'); } $has_license_payload = isset($body['license']) || isset($body['pluginVersion']) || isset($body['version']); if (200 !== $code) { if ($has_license_payload) { $this->store_license_data($body); } else { $this->clear_cached_license_data(); } $error_message = isset($body['error']) ? $body['error'] : 'Licentie verificatie mislukt.'; return new WP_Error('verification_failed', $error_message); } if (empty($body['valid'])) { if ($has_license_payload) { $this->store_license_data($body); } else { $this->clear_cached_license_data(); } return new WP_Error('invalid_license', 'Licentie is ongeldig.'); } $this->store_license_data($body); return $body; } public function is_license_valid() { $data = $this->get_license_data(); if (empty($data) || empty($data['key'])) { return false; } if (isset($data['licenseValid'])) { return (bool) $data['licenseValid']; } return true; } public function get_latest_known_version() { $this->get_plugin_info(); if (!empty($this->plugin_response['version'])) { return $this->normalize_version($this->plugin_response['version']); } $license_data = $this->get_license_data(); if (isset($license_data['pluginVersion']) && $license_data['pluginVersion']) { return $this->normalize_version($license_data['pluginVersion']); } return null; } public function admin_notices() { if (!current_user_can('manage_options')) { return; } if (!$this->is_license_valid()) { $settings_url = admin_url('options-general.php?page=siti-plugin-licenses'); echo '

'; printf( esc_html__('%s: Licentie ongeldig of niet ingesteld. Ga naar %s om je licentie in te voeren.', 'siti-updater'), esc_html($this->plugin['Name']), '' . esc_html__('plugin licenties', 'siti-updater') . '' ); echo '

'; } } public function daily_license_check() { $result = $this->verify_license(); if (is_wp_error($result)) { error_log($this->plugin['Name'] . ' License check failed: ' . $result->get_error_message()); } } public function add_global_settings_page() { add_options_page( __('Plugin Licenties', 'siti-updater'), __('Plugin Licenties', 'siti-updater'), 'manage_options', 'siti-plugin-licenses', array($this, 'render_global_settings_page') ); } public function render_global_settings_page() { if (!current_user_can('manage_options')) { return; } if (isset($_POST['siti_updater_save']) && wp_verify_nonce($_POST['_wpnonce'], 'siti_updater_save')) { foreach (self::$instances as $prefix => $instance) { $key = $prefix . 'license_key'; if (isset($_POST[$key])) { $instance->set_license_key(sanitize_text_field($_POST[$key])); $result = $instance->verify_license(); if (is_wp_error($result)) { $plugin_data = $instance->get_plugin_data(); add_settings_error('siti_updater', 'license_error_' . $prefix, $plugin_data['Name'] . ': ' . $result->get_error_message()); } else { $plugin_data = $instance->get_plugin_data(); add_settings_error('siti_updater', 'license_success_' . $prefix, $plugin_data['Name'] . ': ' . __('Licentie succesvol opgeslagen en geverifieerd.', 'siti-updater'), 'updated'); } } } } ?>

$instance): $license_data = $instance->get_license_data(); $is_valid = $instance->is_license_valid(); $plugin_data = $instance->get_plugin_data(); $current_version = $plugin_data['Version']; $latest_known = $instance->get_latest_known_version(); $latest_version = $latest_known ? $latest_known : (isset($license_data['pluginVersion']) ? $license_data['pluginVersion'] : '-'); ?>

✓ ' . esc_html__('Ja', 'siti-updater') . '' : '✗ ' . esc_html__('Nee', 'siti-updater') . ''; ?> ')): ?>