'Update URI' ) ); $uri = isset( $data['UpdateURI'] ) ? trim( $data['UpdateURI'] ) : ''; if ( '' === $uri ) { $cached = true; return $cached; } // empty → wp.org default if ( false !== stripos( $uri, 'wordpress.org' ) ) { $cached = true; return $cached; } // explicit wp.org $cached = false; // points at Gitea / other → custom updater runs return $cached; } // Short-circuit: stop here entirely if wp.org is handling updates. if ( radio_should_skip_custom_updater() ) { return; } if ( ! defined( 'RADIO_GITEA_HOST' ) ) { define( 'RADIO_GITEA_HOST', 'https://git.davidtkeane.com' ); } if ( ! defined( 'RADIO_GITEA_OWNER' ) ) { define( 'RADIO_GITEA_OWNER', 'ranger' ); } if ( ! defined( 'RADIO_GITEA_REPO' ) ) { define( 'RADIO_GITEA_REPO', 'a-radio' ); } function radio_gitea_repo_url() { return RADIO_GITEA_HOST . '/' . RADIO_GITEA_OWNER . '/' . RADIO_GITEA_REPO; } function radio_gitea_releases_url() { return radio_gitea_repo_url() . '/releases'; } /** * Fetch the latest release/tag, normalised. Returns null on hard * error, or an array including `version`. */ function radio_fetch_latest_release( $force_refresh = false ) { $cache_key = 'radio_gitea_latest'; if ( ! $force_refresh ) { $cached = get_site_transient( $cache_key ); if ( is_array( $cached ) ) { return $cached; } } $base_api = RADIO_GITEA_HOST . '/api/v1/repos/' . RADIO_GITEA_OWNER . '/' . RADIO_GITEA_REPO; // Try formal Release first. $response = wp_remote_get( $base_api . '/releases/latest', array( 'timeout' => 8 ) ); if ( is_wp_error( $response ) ) { return null; } $code = (int) wp_remote_retrieve_response_code( $response ); $body = ( $code === 200 ) ? json_decode( wp_remote_retrieve_body( $response ), true ) : null; // Fallback to /tags if no Release object exists yet. if ( $code !== 200 || ! is_array( $body ) || empty( $body['tag_name'] ) ) { $tags_response = wp_remote_get( $base_api . '/tags?limit=1', array( 'timeout' => 8 ) ); if ( ! is_wp_error( $tags_response ) && (int) wp_remote_retrieve_response_code( $tags_response ) === 200 ) { $tags = json_decode( wp_remote_retrieve_body( $tags_response ), true ); if ( is_array( $tags ) && ! empty( $tags[0]['name'] ) ) { $body = array( 'tag_name' => $tags[0]['name'], 'html_url' => radio_gitea_repo_url() . '/src/tag/' . rawurlencode( $tags[0]['name'] ), 'body' => isset( $tags[0]['message'] ) ? $tags[0]['message'] : '', 'published_at' => isset( $tags[0]['commit']['created'] ) ? $tags[0]['commit']['created'] : null, 'assets' => array(), ); $code = 200; } } } if ( $code !== 200 || ! is_array( $body ) || empty( $body['tag_name'] ) ) { $info = array( 'version' => null, 'html_url' => radio_gitea_releases_url(), 'download_url' => null, 'body' => '', 'published_at' => null, 'error_code' => $code, ); set_site_transient( $cache_key, $info, HOUR_IN_SECONDS ); return $info; } $version = ltrim( (string) $body['tag_name'], 'vV' ); // Prefer a .zip asset; fall back to Gitea source-archive URL. $download_url = null; if ( ! empty( $body['assets'] ) && is_array( $body['assets'] ) ) { foreach ( $body['assets'] as $asset ) { if ( isset( $asset['name'], $asset['browser_download_url'] ) && substr( strtolower( $asset['name'] ), -4 ) === '.zip' ) { $download_url = $asset['browser_download_url']; break; } } } if ( ! $download_url ) { $download_url = radio_gitea_repo_url() . '/archive/' . rawurlencode( $body['tag_name'] ) . '.zip'; } $info = array( 'version' => $version, 'html_url' => isset( $body['html_url'] ) ? esc_url_raw( $body['html_url'] ) : '', 'download_url' => esc_url_raw( $download_url ), 'body' => isset( $body['body'] ) ? wp_strip_all_tags( $body['body'] ) : '', 'published_at' => isset( $body['published_at'] ) ? $body['published_at'] : null, ); set_site_transient( $cache_key, $info, 12 * HOUR_IN_SECONDS ); return $info; } function radio_update_status( $force_refresh = false ) { $current = defined( 'RADIO_VERSION' ) ? RADIO_VERSION : '0.0.0'; $latest = radio_fetch_latest_release( $force_refresh ); if ( ! $latest || empty( $latest['version'] ) ) { $msg = __( 'No releases tagged on the Gitea repo yet.', 'a-radio' ); if ( $latest && ! empty( $latest['error_code'] ) && (int) $latest['error_code'] !== 404 ) { /* translators: %d = HTTP status code returned by the Gitea API */ $msg = sprintf( __( 'Could not reach Gitea (HTTP %d). Try again in a few minutes.', 'a-radio' ), (int) $latest['error_code'] ); } return array( 'status' => 'unknown', 'current' => $current, 'message' => $msg, 'repo_url' => radio_gitea_repo_url(), ); } if ( version_compare( $latest['version'], $current, '>' ) ) { return array( 'status' => 'available', 'current' => $current, 'latest' => $latest['version'], 'html_url' => $latest['html_url'], 'download_url' => $latest['download_url'], 'published_at' => $latest['published_at'], 'body' => $latest['body'], /* translators: 1: latest version available; 2: version currently installed */ 'message' => sprintf( __( 'A new version (v%1$s) is available — you are on v%2$s.', 'a-radio' ), $latest['version'], $current ), ); } return array( 'status' => 'up-to-date', 'current' => $current, 'latest' => $latest['version'], /* translators: %s = current installed version */ 'message' => sprintf( __( 'You are up to date (v%s).', 'a-radio' ), $current ), 'repo_url' => radio_gitea_repo_url(), ); } add_action( 'wp_ajax_radio_check_updates', 'radio_ajax_check_updates' ); function radio_ajax_check_updates() { if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( 'Insufficient permissions.', 403 ); } check_ajax_referer( 'radio_check_updates', 'nonce' ); delete_site_transient( 'radio_gitea_latest' ); wp_send_json_success( radio_update_status( true ) ); } function radio_render_updates_panel() { $status = radio_update_status( false ); $nonce = wp_create_nonce( 'radio_check_updates' ); $repo_url = radio_gitea_repo_url(); $rel_url = radio_gitea_releases_url(); ?>