- Eltern-Ordner ist jetzt EIN Git-Repo (statt getrennter Repos). - root .gitignore haelt Secrets (.env), node_modules, DB und Build-Artefakte raus. - release.ps1: manueller Release (ZIP bauen + ans Backend laden). - root README mit Struktur und Release-Ablauf. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
140 lines
4.1 KiB
PHP
140 lines
4.1 KiB
PHP
<?php
|
|
defined( 'ABSPATH' ) || exit;
|
|
|
|
/**
|
|
* Self-hosted update delivery. Asks the license backend whether a newer version
|
|
* exists and, if so, injects it into WordPress' update flow. The package is only
|
|
* served to licensed, activated sites (the backend gates the download).
|
|
*
|
|
* Without an active license nothing is offered (CB_License::gate_updates() is the
|
|
* additional safety net that strips any stray update entry).
|
|
*/
|
|
class CB_Updater {
|
|
|
|
const TRANSIENT = 'cb_update_info';
|
|
const CACHE_TTL = 6 * HOUR_IN_SECONDS;
|
|
|
|
public static function init(): void {
|
|
add_filter( 'pre_set_site_transient_update_plugins', [ __CLASS__, 'inject' ] );
|
|
add_filter( 'plugins_api', [ __CLASS__, 'plugin_info' ], 20, 3 );
|
|
add_action( 'upgrader_process_complete', [ __CLASS__, 'flush_cache' ], 10, 0 );
|
|
}
|
|
|
|
private static function basename(): string {
|
|
return plugin_basename( CB_FILE );
|
|
}
|
|
|
|
private static function slug(): string {
|
|
return dirname( self::basename() ); // e.g. "gdpr-content-blocker"
|
|
}
|
|
|
|
public static function flush_cache(): void {
|
|
delete_transient( self::TRANSIENT );
|
|
}
|
|
|
|
/**
|
|
* Fetch update info from the backend (cached). Returns the decoded array
|
|
* or null when unlicensed / on error.
|
|
*/
|
|
private static function fetch_info(): ?array {
|
|
if ( ! CB_License::is_active() ) {
|
|
return null;
|
|
}
|
|
|
|
$cached = get_transient( self::TRANSIENT );
|
|
if ( is_array( $cached ) ) {
|
|
return $cached;
|
|
}
|
|
|
|
$lic = CB_License::get_license();
|
|
|
|
$response = wp_remote_post( CB_License::api_url() . '/api/v1/update', [
|
|
'timeout' => 15,
|
|
'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json' ],
|
|
'body' => wp_json_encode( [
|
|
'key' => $lic['key'],
|
|
'product' => CB_PRODUCT_SLUG,
|
|
'domain' => CB_License::domain(),
|
|
'version' => CB_VERSION,
|
|
] ),
|
|
] );
|
|
|
|
if ( is_wp_error( $response ) ) {
|
|
return null;
|
|
}
|
|
|
|
$data = json_decode( wp_remote_retrieve_body( $response ), true );
|
|
if ( ! is_array( $data ) || empty( $data['ok'] ) ) {
|
|
return null;
|
|
}
|
|
|
|
set_transient( self::TRANSIENT, $data, self::CACHE_TTL );
|
|
return $data;
|
|
}
|
|
|
|
/** Inject the update into the plugins update transient. */
|
|
public static function inject( mixed $transient ): mixed {
|
|
if ( ! is_object( $transient ) ) {
|
|
return $transient;
|
|
}
|
|
|
|
$info = self::fetch_info();
|
|
if ( ! $info || empty( $info['update_available'] ) || empty( $info['package'] ) ) {
|
|
return $transient;
|
|
}
|
|
|
|
// Only offer if the backend's version is actually newer than ours.
|
|
if ( version_compare( $info['version'] ?? '0', CB_VERSION, '<=' ) ) {
|
|
return $transient;
|
|
}
|
|
|
|
$item = [
|
|
'slug' => self::slug(),
|
|
'plugin' => self::basename(),
|
|
'new_version' => (string) $info['version'],
|
|
'package' => esc_url_raw( $info['package'] ),
|
|
'url' => 'https://lucas-orth.de',
|
|
'tested' => (string) ( $info['tested'] ?? '' ),
|
|
'requires' => (string) ( $info['requires'] ?? '' ),
|
|
'requires_php'=> (string) ( $info['requires_php'] ?? '' ),
|
|
'icons' => [],
|
|
'banners' => [],
|
|
];
|
|
|
|
$transient->response[ self::basename() ] = (object) $item;
|
|
return $transient;
|
|
}
|
|
|
|
/**
|
|
* Provide the "View version details" popup content.
|
|
*/
|
|
public static function plugin_info( mixed $result, string $action, object $args ): mixed {
|
|
if ( $action !== 'plugin_information' ) {
|
|
return $result;
|
|
}
|
|
if ( empty( $args->slug ) || $args->slug !== self::slug() ) {
|
|
return $result;
|
|
}
|
|
|
|
$info = self::fetch_info();
|
|
if ( ! $info ) {
|
|
return $result;
|
|
}
|
|
|
|
return (object) [
|
|
'name' => 'GDPR Content Blocker',
|
|
'slug' => self::slug(),
|
|
'version' => (string) ( $info['version'] ?? CB_VERSION ),
|
|
'author' => '<a href="https://lucas-orth.de">Lucas Orth</a>',
|
|
'homepage' => 'https://lucas-orth.de',
|
|
'requires' => (string) ( $info['requires'] ?? '' ),
|
|
'tested' => (string) ( $info['tested'] ?? '' ),
|
|
'requires_php' => (string) ( $info['requires_php'] ?? '' ),
|
|
'download_link' => esc_url_raw( $info['package'] ?? '' ),
|
|
'sections' => [
|
|
'changelog' => wp_kses_post( $info['changelog'] ?? '' ),
|
|
],
|
|
];
|
|
}
|
|
}
|