chore: monorepo - plugin, backend und hilfsdaten in einem repo
- 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>
This commit is contained in:
139
gdpr-content-blocker/includes/class-updater.php
Normal file
139
gdpr-content-blocker/includes/class-updater.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?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'] ?? '' ),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user