360 lines
10 KiB
PHP
360 lines
10 KiB
PHP
<?php
|
|
/**
|
|
* Plugin Name: KGV Updater
|
|
* Plugin URI: https://apex-project.de/
|
|
* Description: Aktualisiert KGV-Plugins direkt aus den Gitea-Repositories.
|
|
* Update URI: https://git.apex-project.de/Wordpress_Plugins/KGV-Updater.git
|
|
* Gitea Plugin URI: https://git.apex-project.de/Wordpress_Plugins/KGV-Updater.git
|
|
* Version: 1.0.5
|
|
* Author: Ronny Grobel
|
|
* Text Domain: kgv-updater
|
|
* License: GPLv2+
|
|
*
|
|
* Php Version 5.6
|
|
*
|
|
* @package WordPress
|
|
* @author Ronny Grobel <dgsoft.de@gmail.com>
|
|
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
|
|
* @version 2026-04-16
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
final class KGV_Updater {
|
|
const GITEA_HOST = 'git.apex-project.de';
|
|
const GITEA_TOKEN = '';
|
|
const INSTALLED_TAGS_OPTION = 'kgv_updater_installed_tags';
|
|
|
|
private static $instance = null;
|
|
|
|
public static function instance() {
|
|
if ( null === self::$instance ) {
|
|
self::$instance = new self();
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
private function __construct() {
|
|
add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'inject_updates' ) );
|
|
add_filter( 'plugins_api', array( $this, 'plugins_api' ), 10, 3 );
|
|
add_action( 'upgrader_process_complete', array( $this, 'mark_installed_release_tags' ), 10, 2 );
|
|
}
|
|
|
|
public function inject_updates( $transient ) {
|
|
if ( empty( $transient->checked ) || ! is_object( $transient ) ) {
|
|
return $transient;
|
|
}
|
|
|
|
$plugins = $this->get_managed_plugins();
|
|
$installed_tags = $this->get_installed_tags();
|
|
|
|
foreach ( $plugins as $plugin_file => $plugin_data ) {
|
|
$current_version = isset( $plugin_data['Version'] ) ? $plugin_data['Version'] : '';
|
|
$repo_url = isset( $plugin_data['UpdateURI'] ) ? $plugin_data['UpdateURI'] : '';
|
|
$release = $this->get_release_data( $repo_url );
|
|
$installed_tag = isset( $installed_tags[ $plugin_file ] ) ? (string) $installed_tags[ $plugin_file ] : '';
|
|
$release_tag = isset( $release['tag'] ) ? (string) $release['tag'] : '';
|
|
|
|
if ( empty( $release['version'] ) ) {
|
|
continue;
|
|
}
|
|
|
|
$tag_already_installed = '' !== $installed_tag && '' !== $release_tag && 0 === strcasecmp( $installed_tag, $release_tag );
|
|
|
|
if ( version_compare( $release['version'], $current_version, '>' ) && ! $tag_already_installed ) {
|
|
$transient->response[ $plugin_file ] = (object) array(
|
|
'id' => $repo_url,
|
|
'slug' => dirname( $plugin_file ),
|
|
'plugin' => $plugin_file,
|
|
'new_version' => $release['version'],
|
|
'url' => $repo_url,
|
|
'package' => $release['package'],
|
|
'tested' => get_bloginfo( 'version' ),
|
|
);
|
|
} else {
|
|
$transient->no_update[ $plugin_file ] = (object) array(
|
|
'id' => $repo_url,
|
|
'slug' => dirname( $plugin_file ),
|
|
'plugin' => $plugin_file,
|
|
'new_version' => $current_version,
|
|
'url' => $repo_url,
|
|
'package' => '',
|
|
);
|
|
}
|
|
}
|
|
|
|
return $transient;
|
|
}
|
|
|
|
public function mark_installed_release_tags( $upgrader, $hook_extra ) {
|
|
if ( ! is_array( $hook_extra ) ) {
|
|
return;
|
|
}
|
|
|
|
if ( empty( $hook_extra['type'] ) || 'plugin' !== $hook_extra['type'] ) {
|
|
return;
|
|
}
|
|
|
|
if ( empty( $hook_extra['action'] ) || 'update' !== $hook_extra['action'] ) {
|
|
return;
|
|
}
|
|
|
|
if ( empty( $hook_extra['plugins'] ) || ! is_array( $hook_extra['plugins'] ) ) {
|
|
return;
|
|
}
|
|
|
|
$managed_plugins = $this->get_managed_plugins();
|
|
if ( empty( $managed_plugins ) ) {
|
|
return;
|
|
}
|
|
|
|
$update_transient = get_site_transient( 'update_plugins' );
|
|
|
|
foreach ( $hook_extra['plugins'] as $plugin_file ) {
|
|
if ( ! isset( $managed_plugins[ $plugin_file ] ) ) {
|
|
continue;
|
|
}
|
|
|
|
$tag = '';
|
|
|
|
if ( is_object( $update_transient ) && isset( $update_transient->response[ $plugin_file ] ) && is_object( $update_transient->response[ $plugin_file ] ) ) {
|
|
$package_url = isset( $update_transient->response[ $plugin_file ]->package ) ? (string) $update_transient->response[ $plugin_file ]->package : '';
|
|
$tag = $this->extract_tag_from_package_url( $package_url );
|
|
}
|
|
|
|
if ( '' === $tag ) {
|
|
$repo_url = isset( $managed_plugins[ $plugin_file ]['UpdateURI'] ) ? (string) $managed_plugins[ $plugin_file ]['UpdateURI'] : '';
|
|
$release = $this->get_release_data( $repo_url );
|
|
$tag = isset( $release['tag'] ) ? (string) $release['tag'] : '';
|
|
}
|
|
|
|
if ( '' !== $tag ) {
|
|
$this->set_installed_tag( $plugin_file, $tag );
|
|
}
|
|
}
|
|
}
|
|
|
|
public function plugins_api( $result, $action, $args ) {
|
|
if ( 'plugin_information' !== $action || empty( $args->slug ) ) {
|
|
return $result;
|
|
}
|
|
|
|
$plugins = $this->get_managed_plugins();
|
|
|
|
foreach ( $plugins as $plugin_file => $plugin_data ) {
|
|
if ( dirname( $plugin_file ) !== $args->slug ) {
|
|
continue;
|
|
}
|
|
|
|
$repo_url = isset( $plugin_data['UpdateURI'] ) ? $plugin_data['UpdateURI'] : '';
|
|
$release = $this->get_release_data( $repo_url );
|
|
$homepage = ! empty( $plugin_data['PluginURI'] ) ? $plugin_data['PluginURI'] : $repo_url;
|
|
|
|
$author_name = isset( $plugin_data['AuthorName'] ) ? (string) $plugin_data['AuthorName'] : '';
|
|
$author_uri = isset( $plugin_data['AuthorURI'] ) ? (string) $plugin_data['AuthorURI'] : '';
|
|
$author_display = $author_name;
|
|
|
|
if ( '' !== $author_name && '' !== $author_uri ) {
|
|
$author_display = sprintf(
|
|
'<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s</a>',
|
|
esc_url( $author_uri ),
|
|
esc_html( $author_name )
|
|
);
|
|
}
|
|
|
|
return (object) array(
|
|
'name' => $plugin_data['Name'],
|
|
'slug' => dirname( $plugin_file ),
|
|
'version' => ! empty( $release['version'] ) ? $release['version'] : $plugin_data['Version'],
|
|
'author' => $author_display,
|
|
'author_profile'=> $author_uri,
|
|
'homepage' => $homepage,
|
|
'plugin_url' => $homepage,
|
|
'sections' => array(
|
|
'description' => ! empty( $plugin_data['Description'] ) ? $plugin_data['Description'] : 'KGV Plugin aus Gitea.',
|
|
'installation' => 'Installation erfolgt wie gewohnt in WordPress. Updates werden automatisch ueber KGV Updater bereitgestellt.',
|
|
'changelog' => 'Aktuelle Version: ' . ( ! empty( $release['version'] ) ? $release['version'] : $plugin_data['Version'] ),
|
|
),
|
|
'download_link' => ! empty( $release['package'] ) ? $release['package'] : '',
|
|
);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
private function get_managed_plugins() {
|
|
if ( ! function_exists( 'get_plugins' ) ) {
|
|
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
|
}
|
|
|
|
$plugins = get_plugins();
|
|
$host = self::GITEA_HOST;
|
|
$managed = array();
|
|
|
|
foreach ( $plugins as $plugin_file => $plugin_data ) {
|
|
$update_uri = isset( $plugin_data['UpdateURI'] ) ? trim( (string) $plugin_data['UpdateURI'] ) : '';
|
|
$name = isset( $plugin_data['Name'] ) ? (string) $plugin_data['Name'] : '';
|
|
|
|
if ( '' === $update_uri || 0 !== strpos( $name, 'KGV' ) ) {
|
|
continue;
|
|
}
|
|
|
|
$uri_host = wp_parse_url( $update_uri, PHP_URL_HOST );
|
|
if ( empty( $uri_host ) || $uri_host !== $host ) {
|
|
continue;
|
|
}
|
|
|
|
$managed[ $plugin_file ] = $plugin_data;
|
|
}
|
|
|
|
return $managed;
|
|
}
|
|
|
|
private function get_release_data( $repo_url ) {
|
|
$cache_key = 'kgv_updater_release_' . md5( $repo_url );
|
|
$cached = get_site_transient( $cache_key );
|
|
|
|
if ( is_array( $cached ) ) {
|
|
return $cached;
|
|
}
|
|
|
|
$repo = $this->parse_repo_url( $repo_url );
|
|
if ( empty( $repo ) ) {
|
|
return array();
|
|
}
|
|
|
|
$headers = array(
|
|
'Accept' => 'application/json',
|
|
'User-Agent' => 'KGV-Updater/1.0',
|
|
);
|
|
|
|
$token = trim( (string) self::GITEA_TOKEN );
|
|
if ( '' !== $token ) {
|
|
$headers['Authorization'] = 'token ' . $token;
|
|
}
|
|
|
|
$release_api = sprintf(
|
|
'%s/api/v1/repos/%s/%s/releases/latest',
|
|
$repo['origin'],
|
|
rawurlencode( $repo['owner'] ),
|
|
rawurlencode( $repo['name'] )
|
|
);
|
|
|
|
$response = wp_remote_get(
|
|
$release_api,
|
|
array(
|
|
'timeout' => 12,
|
|
'headers' => $headers,
|
|
)
|
|
);
|
|
|
|
$tag = '';
|
|
if ( ! is_wp_error( $response ) && 200 === (int) wp_remote_retrieve_response_code( $response ) ) {
|
|
$body = json_decode( wp_remote_retrieve_body( $response ), true );
|
|
$tag = isset( $body['tag_name'] ) ? (string) $body['tag_name'] : '';
|
|
}
|
|
|
|
if ( '' === $tag ) {
|
|
$tags_api = sprintf(
|
|
'%s/api/v1/repos/%s/%s/tags?page=1&limit=1',
|
|
$repo['origin'],
|
|
rawurlencode( $repo['owner'] ),
|
|
rawurlencode( $repo['name'] )
|
|
);
|
|
|
|
$tag_response = wp_remote_get(
|
|
$tags_api,
|
|
array(
|
|
'timeout' => 12,
|
|
'headers' => $headers,
|
|
)
|
|
);
|
|
|
|
if ( ! is_wp_error( $tag_response ) && 200 === (int) wp_remote_retrieve_response_code( $tag_response ) ) {
|
|
$body = json_decode( wp_remote_retrieve_body( $tag_response ), true );
|
|
if ( is_array( $body ) && ! empty( $body[0]['name'] ) ) {
|
|
$tag = (string) $body[0]['name'];
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( '' === $tag ) {
|
|
return array();
|
|
}
|
|
|
|
$data = array(
|
|
'version' => ltrim( $tag, 'vV' ),
|
|
'tag' => $tag,
|
|
'package' => sprintf(
|
|
'%s/%s/%s/archive/%s.zip',
|
|
$repo['origin'],
|
|
$repo['owner'],
|
|
$repo['name'],
|
|
rawurlencode( $tag )
|
|
),
|
|
);
|
|
|
|
set_site_transient( $cache_key, $data, HOUR_IN_SECONDS );
|
|
|
|
return $data;
|
|
}
|
|
|
|
private function parse_repo_url( $repo_url ) {
|
|
$parts = wp_parse_url( $repo_url );
|
|
if ( empty( $parts['host'] ) || empty( $parts['path'] ) ) {
|
|
return array();
|
|
}
|
|
|
|
$path = trim( $parts['path'], '/' );
|
|
$bits = explode( '/', $path );
|
|
if ( count( $bits ) < 2 ) {
|
|
return array();
|
|
}
|
|
|
|
$owner = $bits[0];
|
|
$name = preg_replace( '/\.git$/', '', $bits[1] );
|
|
$scheme = ! empty( $parts['scheme'] ) ? $parts['scheme'] : 'https';
|
|
|
|
return array(
|
|
'origin' => $scheme . '://' . $parts['host'],
|
|
'owner' => $owner,
|
|
'name' => $name,
|
|
);
|
|
}
|
|
|
|
private function extract_tag_from_package_url( $package_url ) {
|
|
if ( '' === $package_url ) {
|
|
return '';
|
|
}
|
|
|
|
$path = (string) wp_parse_url( $package_url, PHP_URL_PATH );
|
|
if ( preg_match( '#/archive/([^/]+)\.zip$#i', $path, $matches ) ) {
|
|
return rawurldecode( $matches[1] );
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
private function get_installed_tags() {
|
|
$tags = get_site_option( self::INSTALLED_TAGS_OPTION, array() );
|
|
|
|
return is_array( $tags ) ? $tags : array();
|
|
}
|
|
|
|
private function set_installed_tag( $plugin_file, $tag ) {
|
|
if ( '' === $plugin_file || '' === $tag ) {
|
|
return;
|
|
}
|
|
|
|
$tags = $this->get_installed_tags();
|
|
$tags[ $plugin_file ] = $tag;
|
|
update_site_option( self::INSTALLED_TAGS_OPTION, $tags );
|
|
}
|
|
|
|
}
|
|
|
|
KGV_Updater::instance();
|