diff --git a/ACTIONS.md b/ACTIONS.md
index cd0b476c..e71e2660 100644
--- a/ACTIONS.md
+++ b/ACTIONS.md
@@ -130,9 +130,13 @@ Fires after an user has been successfully created or logged-in via the OAuth 2.0
---
-### `do_action( 'fictioneer_after_update' )`
+### `do_action( 'fictioneer_after_update', $new_version, $previous_version )`
Fires after the theme has been updated, once per version change.
+**Parameters:**
+* $new_version (string) – The new version tag (e.g. v5.19.1).
+* $previous_version (string) – The previous version tag (e.g. v5.19.0).
+
**Hooked Actions:**
* `fictioneer_purge_caches_after_update()` – Purges selected caches and Transients. Priority 10.
diff --git a/INSTALLATION.md b/INSTALLATION.md
index 8ec4b3e8..8ba59669 100644
--- a/INSTALLATION.md
+++ b/INSTALLATION.md
@@ -1479,7 +1479,7 @@ define( 'CONSTANT_NAME', value );
| FICTIONEER_AJAX_LOGIN_TTL | integer | How long to cache AJAX authentications locally in _milliseconds_. Default `15000`.
| FICTIONEER_AJAX_POST_DEBOUNCE_RATE | integer | How long to debounce AJAX requests of the same type in _milliseconds_. Default `700`.
| FICTIONEER_AUTHOR_KEYWORD_SEARCH_LIMIT | integer | Maximum number of authors in the advanced search suggestions. Default `100`.
-| FICTIONEER_UPDATE_CHECK_TIMEOUT | integer | Timeout between checks for theme updates in _seconds_. Default `3600`.
+| FICTIONEER_UPDATE_CHECK_TIMEOUT | integer | Timeout between checks for theme updates in _seconds_. Default `43200`.
| FICTIONEER_API_STORYGRAPH_CACHE_TTL | integer | How long Storygraph responses are cached in _seconds_. Default `3600`.
| FICTIONEER_API_STORYGRAPH_STORIES_PER_PAGE | integer | How many items the Storygraph `/stories` endpoint returns. Default 10.
| FICTIONEER_MAX_CUSTOM_PAGES_PER_STORY | integer | Maximum number of story custom pages. Default `4`.
diff --git a/includes/functions/_setup-admin.php b/includes/functions/_setup-admin.php
index 3782e6c8..aff1c8e1 100644
--- a/includes/functions/_setup-admin.php
+++ b/includes/functions/_setup-admin.php
@@ -111,114 +111,130 @@ add_action( 'admin_enqueue_scripts', 'fictioneer_admin_scripts' );
// CHECK FOR UPDATES
// =============================================================================
-if ( ! function_exists( 'fictioneer_check_for_updates' ) ) {
- /**
- * Check Github repository for a new release
- *
- * Makes a remote request to the Github API to check the latest release and,
- * if a newer version tag than what is installed is returned, updates the
- * 'fictioneer_latest_version' option. Only one request is made every 12 hours
- * unless you are on the updates page.
- *
- * @since 5.0.0
- * @since 5.7.5 - Refactored.
- *
- * @return boolean True if there is a newer version, false if not.
- */
+/**
+ * Check Github repository for a new release
+ *
+ * @since 5.0.0
+ * @since 5.7.5 - Refactored.
+ * @since 5.19.1 - Refactored again.
+ *
+ * @return boolean True if there is a newer version, false if not.
+ */
- function fictioneer_check_for_updates() {
- global $pagenow;
+function fictioneer_check_for_updates() {
+ global $pagenow;
- // Setup
- $last_check = (int) get_option( 'fictioneer_update_check_timestamp', 0 );
- $latest_version = get_option( 'fictioneer_latest_version', FICTIONEER_RELEASE_TAG );
- $is_updates_page = $pagenow === 'update-core.php';
+ // Setup
+ $theme_info = fictioneer_get_theme_info();
+ $last_check_timestamp = strtotime( $theme_info['last_update_check'] ?? 0 );
+ $remote_version = $theme_info['last_update_version'];
+ $is_updates_page = $pagenow === 'update-core.php';
- // Only call API every n seconds, otherwise check database
- if ( ! empty( $latest_version ) && time() < $last_check + FICTIONEER_UPDATE_CHECK_TIMEOUT && ! $is_updates_page ) {
- return version_compare( $latest_version, FICTIONEER_RELEASE_TAG, '>' );
- }
-
- // Remember this check
- update_option( 'fictioneer_update_check_timestamp', time() );
-
- // Request to repository
- $response = wp_remote_get(
- 'https://api.github.com/repos/Tetrakern/fictioneer/releases/latest',
- array(
- 'headers' => array(
- 'User-Agent' => 'FICTIONEER',
- 'Accept' => 'application/vnd.github+json',
- 'X-GitHub-Api-Version' => '2022-11-28'
- )
- )
- );
-
- // Abort if request failed or is not a 2xx success status code
- if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) >= 300 ) {
- return false;
- }
-
- // Decode JSON to array
- $release = json_decode( wp_remote_retrieve_body( $response ), true );
- $release_tag = sanitize_text_field( $release['tag_name'] ?? '' );
-
- // Abort if request did not return expected data
- if ( ! $release_tag ) {
- return false;
- }
-
- // Remember latest version
- update_option( 'fictioneer_latest_version', $release_tag );
-
- // Compare with currently installed version
- return version_compare( $release_tag, FICTIONEER_RELEASE_TAG, '>' );
+ // Only call API every n seconds, otherwise check database
+ if (
+ $remote_version &&
+ ! $is_updates_page &&
+ current_time( 'timestamp', true ) < $last_check_timestamp + FICTIONEER_UPDATE_CHECK_TIMEOUT
+ ) {
+ return version_compare( $remote_version, FICTIONEER_RELEASE_TAG, '>' );
}
+
+ // Remember this check
+ $theme_info['last_update_check'] = current_time( 'mysql', 1 );
+
+ // Request to repository
+ $response = wp_remote_get(
+ 'https://api.github.com/repos/Tetrakern/fictioneer/releases/latest',
+ array(
+ 'headers' => array(
+ 'User-Agent' => 'FICTIONEER',
+ 'Accept' => 'application/vnd.github+json',
+ 'X-GitHub-Api-Version' => '2022-11-28'
+ )
+ )
+ );
+
+ // Abort if request failed or is not a 2xx success status code
+ if ( is_wp_error( $response ) || wp_remote_retrieve_response_code( $response ) >= 300 ) {
+ return false;
+ }
+
+ // Decode JSON to array
+ $release = json_decode( wp_remote_retrieve_body( $response ), true );
+ $release_tag = sanitize_text_field( $release['tag_name'] ?? '' );
+
+ // Abort if request did not return expected data
+ if ( ! $release_tag ) {
+ return false;
+ }
+
+ // Add to theme info
+ $theme_info['last_update_version'] = $release_tag;
+ $theme_info['last_update_notes'] = sanitize_textarea_field( $release['body'] ?? '' );
+ $theme_info['last_update_nag'] = ''; // Reset
+
+ if ( $release['assets'] ?? 0 ) {
+ $theme_info['last_version_download_url'] = sanitize_url( $release['assets'][0]['browser_download_url'] ?? '' );
+ } else {
+ $theme_info['last_version_download_url'] = '';
+ }
+
+ // Update info in database
+ update_option( 'fictioneer_theme_info', $theme_info );
+
+ // Compare with currently installed version
+ return version_compare( $release_tag, FICTIONEER_RELEASE_TAG, '>' );
}
/**
* Show notice when a newer version is available
*
* @since 5.0.0
+ * @since 5.19.1 - Refactored.
*/
function fictioneer_admin_update_notice() {
- global $pagenow;
-
- // Setup
- $last_notice = (int) get_option( 'fictioneer_update_notice_timestamp', 0 );
- $is_updates_page = $pagenow == 'update-core.php';
-
- // Show only once every n seconds
- if ( $last_notice + FICTIONEER_UPDATE_CHECK_TIMEOUT > time() && ! $is_updates_page ) {
+ // Guard
+ if ( ! current_user_can( 'install_themes' ) || ! fictioneer_check_for_updates() ) {
return;
}
- // Update?
- if ( ! fictioneer_check_for_updates() ) {
+ global $pagenow;
+
+ // Setup
+ $theme_info = fictioneer_get_theme_info();
+ $last_update_nag = strtotime( $theme_info['last_update_nag'] ?? 0 );
+ $is_updates_page = $pagenow == 'update-core.php';
+
+ // Show only once every n seconds
+ if ( ! $is_updates_page && current_time( 'timestamp', true ) < $last_update_nag + 60 ) {
return;
}
// Render notice
+ $notes = fictioneer_prepare_release_notes( $theme_info['last_update_notes'] ?? '' );
+
wp_admin_notice(
sprintf(
- __( 'Fictioneer %1$s is available. Please download and install the latest version at your next convenience.', 'fictioneer' ),
- get_option( 'fictioneer_latest_version', FICTIONEER_RELEASE_TAG ),
- 'https://github.com/Tetrakern/fictioneer/releases'
+ __( 'Fictioneer %1$s is available. Please download and install the latest version at your next convenience.%3$s', 'fictioneer' ),
+ $theme_info['last_update_version'],
+ 'https://github.com/Tetrakern/fictioneer/releases',
+ $notes ? '' . __( 'Release Notes', 'fictioneer' ) . '
' . $notes . '
Fictioneer %1$s is available. Please download and install the latest version at your next convenience.', 'fictioneer' ), - get_option( 'fictioneer_latest_version', FICTIONEER_RELEASE_TAG ), + $theme_info['last_update_version'], 'https://github.com/Tetrakern/fictioneer/releases' ); ?>