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( '%2$s', 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();