Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions functionalities.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ function () {
);

\add_action( 'updated_option', array( '\Functionalities\Core\Module_Registry', 'handle_option_update' ), 10, 3 );
\add_action( 'added_option', array( '\Functionalities\Core\Module_Registry', 'handle_option_add' ), 10, 2 );

// Activation hook.
\register_activation_hook(
Expand Down
14 changes: 14 additions & 0 deletions includes/core/class-module-registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,20 @@ public static function handle_option_update( string $option, $old_value, $value
}
}

/**
* React when settings are saved for the first time.
*
* WordPress fires added_option instead of updated_option when an option did
* not previously exist, which is the normal fresh-install PWA path.
*
* @param string $option Option name.
* @param mixed $value New value.
* @return void
*/
public static function handle_option_add( string $option, $value ): void {
self::handle_option_update( $option, null, $value );
}

/**
* Build one normalized definition.
*
Expand Down
4 changes: 3 additions & 1 deletion includes/features/class-pwa.php
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,9 @@ private static function output_offline_page(): void {
ob_end_clean();
}

\status_header( 503 );
// This application shell is fetched during service-worker installation.
// cache.addAll() rejects non-2xx responses, so it must be cacheable.
\status_header( 200 );
\nocache_headers();

?>
Expand Down
1 change: 1 addition & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ Before uninstalling, go to the Functionalities dashboard and check **"Delete all
== Changelog ==

= 1.4.8 =
* Fixed: Fresh PWA settings now register rewrite endpoints immediately, and the offline application shell returns a cacheable success response so service-worker precaching can complete.
* Added: True lazy module registry. A frontend request with all modules disabled loads no feature class files; enabling one module loads only that feature and shared dependencies.
* Added: Versioned settings export/import with dry-run differences, module validation, default custom-code redaction, and an explicit code opt-in.
* Added: Privacy-conscious diagnostics download with software versions, enabled modules, writable-path status, and rewrite-rule health. Task content, redirects, users, secrets, and site URLs are excluded.
Expand Down
2 changes: 2 additions & 0 deletions tests/ModuleRegistryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public function test_pwa_boots_safely_before_wordpress_init(): void {

$this->assertSame( array( 'class-pwa.php' ), $result['features'] );
$this->assertContains( 'init', $result['hooks'] );
$this->assertContains( 'added_option', $result['hooks'] );
$this->assertContains( 'updated_option', $result['hooks'] );
}

/**
Expand Down
26 changes: 26 additions & 0 deletions tests/PwaOfflineStatusTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php
/**
* PWA offline response regression test.
*
* @package FunctionalitiesTests
*/

use PHPUnit\Framework\TestCase;

final class PwaOfflineStatusTest extends TestCase {
/**
* The offline shell must be a successful response for cache.addAll().
*
* @return void
*/
public function test_offline_shell_is_cacheable_during_service_worker_install(): void {
$source = file_get_contents( dirname( __DIR__ ) . '/includes/features/class-pwa.php' );

$this->assertIsString( $source );
$this->assertMatchesRegularExpression(
'/private static function output_offline_page\(\).*?status_header\( 200 \)/s',
$source
);
$this->assertStringContainsString( 'c.addAll(PRECACHE_URLS)', $source );
}
}
Loading