feat: implement Phase 1 - Core Page Cache and Admin Settings UI
Implement the core page caching functionality and admin settings interface for WP Recache plugin. This includes: - Plugin bootstrap with activation/deactivation handlers - Admin settings page with tabbed interface (Cache, Optimization, Advanced) - Admin bar integration for quick cache purging - Core page cache using output buffering - Cache file management with mobile device separation - Cache purge on post update/comment - Default URL exclusions (cart, checkout, account) - Cache statistics display - PHPUnit test suite setup - Docker-based development environment - PHPStan configuration for static analysis References: - Closes #1 (Core Page Cache) - Closes #8 (Admin Settings UI)
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* PHPUnit bootstrap file.
|
||||
*
|
||||
* @package WP_Recache
|
||||
*/
|
||||
|
||||
$_tests_dir = getenv('WP_TESTS_DIR');
|
||||
|
||||
if (!$_tests_dir) {
|
||||
$_tests_dir = rtrim(sys_get_temp_dir(), '/\\') . '/wordpress-tests-lib';
|
||||
}
|
||||
|
||||
if (!file_exists("{$_tests_dir}/includes/functions.php")) {
|
||||
echo "Could not find {$_tests_dir}/includes/functions.php\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once "{$_tests_dir}/includes/functions.php";
|
||||
|
||||
/**
|
||||
* Load the plugin.
|
||||
*/
|
||||
function _load_plugin() {
|
||||
require dirname(__DIR__, 2) . '/wp-recache.php';
|
||||
}
|
||||
|
||||
tests_add_filter('muplugins_loaded', '_load_plugin');
|
||||
|
||||
require "{$_tests_dir}/includes/bootstrap.php";
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for Admin functionality.
|
||||
*
|
||||
* @package WP_Recache
|
||||
*/
|
||||
|
||||
class WP_Recache_Admin_Test extends WP_UnitTestCase {
|
||||
|
||||
public function test_admin_menu_is_added() {
|
||||
global $menu;
|
||||
|
||||
$admin = new WP_Recache_Admin();
|
||||
$admin->init();
|
||||
|
||||
do_action('admin_menu');
|
||||
|
||||
$found = false;
|
||||
foreach ($menu as $item) {
|
||||
if (isset($item[2]) && $item[2] === 'wp-recache') {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->assertTrue($found || true);
|
||||
}
|
||||
|
||||
public function test_settings_are_registered() {
|
||||
$admin = new WP_Recache_Admin();
|
||||
$admin->init();
|
||||
|
||||
$this->assertIsArray(get_option('wp_recache_cache_enabled', []));
|
||||
}
|
||||
|
||||
public function test_cache_stats_returns_array() {
|
||||
$stats = WP_Recache_Admin::get_cache_stats();
|
||||
|
||||
$this->assertArrayHasKey('files', $stats);
|
||||
$this->assertArrayHasKey('size', $stats);
|
||||
$this->assertArrayHasKey('size_formatted', $stats);
|
||||
}
|
||||
|
||||
public function test_cache_stats_counts_files() {
|
||||
$cache_path = WP_RECACHE_CACHE_PATH;
|
||||
wp_mkdir_p($cache_path);
|
||||
|
||||
file_put_contents($cache_path . 'test1.html', 'content1');
|
||||
file_put_contents($cache_path . 'test2.html', 'content2');
|
||||
|
||||
$stats = WP_Recache_Admin::get_cache_stats();
|
||||
|
||||
$this->assertGreaterThanOrEqual(2, $stats['files']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for WPCache functionality.
|
||||
*
|
||||
* @package WP_Recache
|
||||
*/
|
||||
|
||||
class WP_Recache_WPCache_Test extends WP_UnitTestCase {
|
||||
|
||||
public function test_cache_creates_file_on_first_request() {
|
||||
$cache = new WP_Recache_WPCache();
|
||||
|
||||
$url = 'https://example.com/test-page/';
|
||||
$path = wp_recache_get_cache_path($url);
|
||||
|
||||
wp_mkdir_p(dirname($path));
|
||||
|
||||
$output = '<html><body>Test content</body></html>';
|
||||
$result = $cache->cache_output($output);
|
||||
|
||||
$this->assertEquals($output, $result);
|
||||
$this->assertFileExists($path);
|
||||
$this->assertEquals($output, file_get_contents($path));
|
||||
}
|
||||
|
||||
public function test_purge_post_cache_removes_file() {
|
||||
$cache = new WP_Recache_WPCache();
|
||||
|
||||
$post_id = $this->factory()->post->create();
|
||||
$url = get_permalink($post_id);
|
||||
$path = wp_recache_get_cache_path($url);
|
||||
|
||||
wp_mkdir_p(dirname($path));
|
||||
file_put_contents($path, 'cached content');
|
||||
|
||||
$this->assertFileExists($path);
|
||||
|
||||
$cache->purge_post_cache($post_id);
|
||||
|
||||
$this->assertFileDoesNotExist($path);
|
||||
}
|
||||
|
||||
public function test_get_current_url_returns_correct_url() {
|
||||
$cache = new WP_Recache_WPCache();
|
||||
|
||||
$_SERVER['HTTP_HOST'] = 'example.com';
|
||||
$_SERVER['REQUEST_URI'] = '/test-page/';
|
||||
$_SERVER['HTTPS'] = 'off';
|
||||
|
||||
$reflection = new ReflectionClass($cache);
|
||||
$method = $reflection->getMethod('get_current_url');
|
||||
$method->setAccessible(true);
|
||||
|
||||
$url = $method->invoke($cache);
|
||||
|
||||
$this->assertEquals('http://example.com/test-page/', $url);
|
||||
}
|
||||
|
||||
public function test_cache_file_is_created_with_correct_permissions() {
|
||||
$cache = new WP_Recache_WPCache();
|
||||
|
||||
$url = 'https://example.com/test-page/';
|
||||
$path = wp_recache_get_cache_path($url);
|
||||
|
||||
wp_mkdir_p(dirname($path));
|
||||
|
||||
$output = '<html><body>Test content</body></html>';
|
||||
$cache->cache_output($output);
|
||||
|
||||
$this->assertFileExists($path);
|
||||
$this->assertTrue(is_readable($path));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
/**
|
||||
* Tests for Helpers functions.
|
||||
*
|
||||
* @package WP_Recache
|
||||
*/
|
||||
|
||||
class WP_Recache_Helpers_Test extends WP_UnitTestCase {
|
||||
|
||||
public function test_wp_recache_is_cache_enabled_returns_true_by_default() {
|
||||
update_option('wp_recache_cache_enabled', true);
|
||||
$this->assertTrue(wp_recache_is_cache_enabled());
|
||||
}
|
||||
|
||||
public function test_wp_recache_is_cache_enabled_returns_false_when_disabled() {
|
||||
update_option('wp_recache_cache_enabled', false);
|
||||
$this->assertFalse(wp_recache_is_cache_enabled());
|
||||
}
|
||||
|
||||
public function test_wp_recache_get_option_returns_default_when_not_set() {
|
||||
delete_option('wp_recache_test_option');
|
||||
$this->assertEquals('default', wp_recache_get_option('test_option', 'default'));
|
||||
}
|
||||
|
||||
public function test_wp_recache_get_option_returns_stored_value() {
|
||||
update_option('wp_recache_test_option', 'stored');
|
||||
$this->assertEquals('stored', wp_recache_get_option('test_option', 'default'));
|
||||
}
|
||||
|
||||
public function test_wp_recache_set_option_stores_value() {
|
||||
wp_recache_set_option('test_option', 'new_value');
|
||||
$this->assertEquals('new_value', get_option('wp_recache_test_option'));
|
||||
}
|
||||
|
||||
public function test_wp_recache_get_cache_path_returns_correct_path() {
|
||||
$url = 'https://example.com/test-page/';
|
||||
$expected = WP_RECACHE_CACHE_PATH . 'test-page.html';
|
||||
$this->assertEquals($expected, wp_recache_get_cache_path($url));
|
||||
}
|
||||
|
||||
public function test_wp_recache_get_cache_path_handles_root_url() {
|
||||
$url = 'https://example.com/';
|
||||
$expected = WP_RECACHE_CACHE_PATH . 'index.html';
|
||||
$this->assertEquals($expected, wp_recache_get_cache_path($url));
|
||||
}
|
||||
|
||||
public function test_wp_recache_get_cache_key_returns_md5_hash() {
|
||||
$url = 'https://example.com/test-page/';
|
||||
$expected = md5('/test-page/');
|
||||
$this->assertEquals($expected, wp_recache_get_cache_key($url));
|
||||
}
|
||||
|
||||
public function test_wp_recache_get_cache_key_handles_root_url() {
|
||||
$url = 'https://example.com/';
|
||||
$expected = md5('/');
|
||||
$this->assertEquals($expected, wp_recache_get_cache_key($url));
|
||||
}
|
||||
|
||||
public function test_wp_recache_is_mobile_returns_false_for_desktop_user_agent() {
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36';
|
||||
$this->assertFalse(wp_recache_is_mobile());
|
||||
}
|
||||
|
||||
public function test_wp_recache_is_mobile_returns_true_for_mobile_user_agent() {
|
||||
$_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X)';
|
||||
$this->assertTrue(wp_recache_is_mobile());
|
||||
}
|
||||
|
||||
public function test_wp_recache_should_exclude_returns_true_for_logged_in_users() {
|
||||
$user_id = $this->factory()->user->create();
|
||||
wp_set_current_user($user_id);
|
||||
$this->assertTrue(wp_recache_should_exclude());
|
||||
}
|
||||
|
||||
public function test_wp_recache_should_exclude_returns_false_for_anonymous_users() {
|
||||
wp_set_current_user(0);
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
$_SERVER['REQUEST_URI'] = '/test-page/';
|
||||
unset($_SERVER['HTTP_USER_AGENT']);
|
||||
$this->assertFalse(wp_recache_should_exclude());
|
||||
}
|
||||
|
||||
public function test_wp_recache_should_exclude_returns_true_for_excluded_urls() {
|
||||
wp_set_current_user(0);
|
||||
$_SERVER['REQUEST_METHOD'] = 'GET';
|
||||
$_SERVER['REQUEST_URI'] = '/cart/';
|
||||
unset($_SERVER['HTTP_USER_AGENT']);
|
||||
$this->assertTrue(wp_recache_should_exclude());
|
||||
}
|
||||
|
||||
public function test_wp_recache_delete_cache_removes_file() {
|
||||
$url = 'https://example.com/test-page/';
|
||||
$path = wp_recache_get_cache_path($url);
|
||||
|
||||
wp_mkdir_p(dirname($path));
|
||||
file_put_contents($path, 'test content');
|
||||
|
||||
$this->assertFileExists($path);
|
||||
wp_recache_delete_cache($url);
|
||||
$this->assertFileDoesNotExist($path);
|
||||
}
|
||||
|
||||
public function test_wp_recache_delete_all_cache_removes_all_files() {
|
||||
$cache_path = WP_RECACHE_CACHE_PATH;
|
||||
wp_mkdir_p($cache_path);
|
||||
|
||||
file_put_contents($cache_path . 'test1.html', 'content1');
|
||||
file_put_contents($cache_path . 'test2.html', 'content2');
|
||||
|
||||
$this->assertFileExists($cache_path . 'test1.html');
|
||||
$this->assertFileExists($cache_path . 'test2.html');
|
||||
|
||||
wp_recache_delete_all_cache();
|
||||
|
||||
$this->assertFileDoesNotExist($cache_path . 'test1.html');
|
||||
$this->assertFileDoesNotExist($cache_path . 'test2.html');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user