Files
s4luorth 6caece78f5 feat: plugin-icon einbinden (auto-erkennung in assets/) (v1.5.1)
CB_Updater::icons() liefert das plugin-icon fuer den Aktualisierungen-screen
und das "Versionsdetails"-popup. Es erkennt automatisch eine icon-datei in
assets/ (icon.svg|png|webp|jpg); ohne datei wird kein icon gesetzt.
Bild wird vom betreiber selbst hinzugefuegt (nicht im repo).

+ version 1.5.1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 14:18:30 +02:00

160 lines
4.8 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;
}
/**
* Plugin icon (shown on the Updates screen + the "View details" popup).
* Auto-detects a bundled icon file in /assets — drop in ONE of:
* assets/icon.svg | assets/icon.png | assets/icon.webp | assets/icon.jpg
* Returns an empty array (no icon) if none is present.
*/
private static function icons(): array {
foreach ( [ 'icon.svg', 'icon.png', 'icon.webp', 'icon.jpg' ] as $file ) {
if ( file_exists( CB_DIR . 'assets/' . $file ) ) {
$url = CB_URL . 'assets/' . $file;
if ( str_ends_with( $file, '.svg' ) ) {
return [ 'svg' => $url ];
}
return [ '1x' => $url, '2x' => $url, 'default' => $url ];
}
}
return [];
}
/** 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' => self::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'] ?? '' ),
'icons' => self::icons(),
'sections' => [
'changelog' => wp_kses_post( $info['changelog'] ?? '' ),
],
];
}
}