fix: auto-install memcached drop-in + block plugin activation
- dekart_try_install_memcached_dropin(): auto-copy object-cache.php from memcached plugin to wp-content/ on plugins_loaded - Remove 'Activate' link for memcached plugin (prevents fatal error) - Admin notice with instructions when PHP extension is missing - WP-CLI command: wp dekart cache-memcached
This commit is contained in:
parent
dcd71303c8
commit
2deb14c736
@ -3,19 +3,23 @@
|
|||||||
* MU-Plugin: Object Cache Bootstrap
|
* MU-Plugin: Object Cache Bootstrap
|
||||||
*
|
*
|
||||||
* Автоопределение backend кеширования + versioned cache + автоинвалидация.
|
* Автоопределение backend кеширования + versioned cache + автоинвалидация.
|
||||||
* Dev → Redis (через redis-cache plugin).
|
|
||||||
* Prod → Memcached (через Memcached Object Cache plugin).
|
|
||||||
* Работает с любым active drop-in (object-cache.php).
|
* Работает с любым active drop-in (object-cache.php).
|
||||||
*
|
*
|
||||||
|
* УСТАНОВКА MEMCACHED НА ПРОДЕ:
|
||||||
|
* 1. Установить PHP-расширение: sudo apt install php-memcache
|
||||||
|
* 2. wp plugin install memcached (установить плагин)
|
||||||
|
* 3. Скопировать drop-in:
|
||||||
|
* cp wp-content/plugins/memcached/object-cache.php wp-content/object-cache.php
|
||||||
|
* 4. Плагин НЕ активировать — он нужен только как источник файла.
|
||||||
|
*
|
||||||
* @package Dekart
|
* @package Dekart
|
||||||
* @version 2.0
|
* @version 2.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// 1. КОНСТАНТЫ ДЛЯ ПЛАГИНОВ (выполняется до загрузки WP)
|
// 1. КОНСТАНТЫ ДЛЯ ПЛАГИНОВ
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
// Redis: константы для redis-cache plugin
|
|
||||||
if ( ! defined( 'WP_REDIS_HOST' ) ) {
|
if ( ! defined( 'WP_REDIS_HOST' ) ) {
|
||||||
define( 'WP_REDIS_HOST', '127.0.0.1' );
|
define( 'WP_REDIS_HOST', '127.0.0.1' );
|
||||||
}
|
}
|
||||||
@ -30,31 +34,23 @@ if ( ! defined( 'WP_REDIS_DATABASE' ) ) {
|
|||||||
// 2. АВТООПРЕДЕЛЕНИЕ BACKEND
|
// 2. АВТООПРЕДЕЛЕНИЕ BACKEND
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
/**
|
|
||||||
* Определить активный backend object cache.
|
|
||||||
*
|
|
||||||
* @return string 'memcached' | 'redis' | 'none'
|
|
||||||
*/
|
|
||||||
function dekart_detect_cache_backend(): string {
|
function dekart_detect_cache_backend(): string {
|
||||||
// 1. По active drop-in: Memcached Object Cache
|
|
||||||
if ( class_exists( 'Memcache' ) || class_exists( 'Memcached' ) ) {
|
if ( class_exists( 'Memcache' ) || class_exists( 'Memcached' ) ) {
|
||||||
$mc_sock = @fsockopen( '127.0.0.1', 11211, $errno, $errstr, 0.5 );
|
$sock = @fsockopen( '127.0.0.1', 11211, $errno, $errstr, 0.5 );
|
||||||
if ( $mc_sock ) {
|
if ( $sock ) {
|
||||||
fclose( $mc_sock );
|
fclose( $sock );
|
||||||
return 'memcached';
|
return 'memcached';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. По active drop-in: Redis (через Predis от redis-cache)
|
|
||||||
if ( class_exists( 'Predis\Client' ) ) {
|
if ( class_exists( 'Predis\Client' ) ) {
|
||||||
$r_sock = @fsockopen( '127.0.0.1', 6379, $errno, $errstr, 0.5 );
|
$sock = @fsockopen( '127.0.0.1', 6379, $errno, $errstr, 0.5 );
|
||||||
if ( $r_sock ) {
|
if ( $sock ) {
|
||||||
fclose( $r_sock );
|
fclose( $sock );
|
||||||
return 'redis';
|
return 'redis';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Есть object-cache.php, но сервис не отвечает
|
|
||||||
if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
|
if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
|
||||||
return 'dropin-no-connection';
|
return 'dropin-no-connection';
|
||||||
}
|
}
|
||||||
@ -66,32 +62,18 @@ function dekart_detect_cache_backend(): string {
|
|||||||
// 3. VERSIONED CACHE KEY
|
// 3. VERSIONED CACHE KEY
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
/**
|
|
||||||
* Текущая версия кеша.
|
|
||||||
*/
|
|
||||||
function my_cache_version(): int {
|
function my_cache_version(): int {
|
||||||
return (int) get_option( 'my_cache_version', 1 );
|
return (int) get_option( 'my_cache_version', 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Обернуть ключ с префиксом версии.
|
|
||||||
* Инвалидация: достаточно изменить версию.
|
|
||||||
*
|
|
||||||
* @param string $key Исходный ключ.
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function my_cache_key( string $key ): string {
|
function my_cache_key( string $key ): string {
|
||||||
return 'v:' . my_cache_version() . ':' . $key;
|
return 'v:' . my_cache_version() . ':' . $key;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// 4. ИНВАЛИДАЦИЯ КЕША (version bump + flush)
|
// 4. ИНВАЛИДАЦИЯ КЕША
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
/**
|
|
||||||
* Сбросить object cache + увеличить версию.
|
|
||||||
* Безопасно от рекурсии — static guard.
|
|
||||||
*/
|
|
||||||
function my_cache_bump_version(): void {
|
function my_cache_bump_version(): void {
|
||||||
static $running = false;
|
static $running = false;
|
||||||
if ( $running ) {
|
if ( $running ) {
|
||||||
@ -106,37 +88,97 @@ function my_cache_bump_version(): void {
|
|||||||
$running = false;
|
$running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// branch_* опции → сброс кеша (настройки филиала)
|
|
||||||
add_action( 'update_option', function ( $option ) {
|
add_action( 'update_option', function ( $option ) {
|
||||||
if ( str_starts_with( $option, 'branch_' ) ) {
|
if ( str_starts_with( $option, 'branch_' ) ) {
|
||||||
my_cache_bump_version();
|
my_cache_bump_version();
|
||||||
}
|
}
|
||||||
}, 10, 1 );
|
}, 10, 1 );
|
||||||
|
|
||||||
// Посты (включая Carbon Fields)
|
|
||||||
add_action( 'save_post', 'my_cache_bump_version' );
|
add_action( 'save_post', 'my_cache_bump_version' );
|
||||||
add_action( 'carbon_fields_post_meta_container_saved', 'my_cache_bump_version' );
|
add_action( 'carbon_fields_post_meta_container_saved', 'my_cache_bump_version' );
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// 5. WP-CLI: установка/сброс кеша
|
// 5. АВТОУСТАНОВКА DROP-IN MEMCACHED (для прода)
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Попробовать установить drop-in Memcached, если:
|
||||||
|
* - плагин memcached установлен,
|
||||||
|
* - object-cache.php ещё нет,
|
||||||
|
* - PHP-расширение Memcache доступно.
|
||||||
|
*/
|
||||||
|
function dekart_try_install_memcached_dropin(): void {
|
||||||
|
$target = WP_CONTENT_DIR . '/object-cache.php';
|
||||||
|
if ( file_exists( $target ) ) {
|
||||||
|
return; // drop-in уже есть
|
||||||
|
}
|
||||||
|
|
||||||
|
$source = WP_CONTENT_DIR . '/plugins/memcached/object-cache.php';
|
||||||
|
if ( ! file_exists( $source ) ) {
|
||||||
|
return; // плагин не установлен
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! class_exists( 'Memcache' ) && ! class_exists( 'Memcached' ) ) {
|
||||||
|
return; // нет PHP-расширения
|
||||||
|
}
|
||||||
|
|
||||||
|
copy( $source, $target );
|
||||||
|
}
|
||||||
|
|
||||||
|
add_action( 'plugins_loaded', 'dekart_try_install_memcached_dropin', 0 );
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// 6. АДМИН-НОТИС + БЛОКИРОВКА АКТИВАЦИИ MEMCACHED PLUGIN
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Убрать ссылку "Активировать" у плагина Memcached Object Cache —
|
||||||
|
* он содержит только object-cache.php, активация вызывает фатальную ошибку.
|
||||||
|
* Файл копируется автоматически через dekart_try_install_memcached_dropin().
|
||||||
|
*/
|
||||||
|
add_filter( 'plugin_action_links_memcached/object-cache.php', function ( $actions ) {
|
||||||
|
unset( $actions['activate'] );
|
||||||
|
$actions['info'] = '<span style="color:#999">drop-in (копируется автоматически)</span>';
|
||||||
|
return $actions;
|
||||||
|
} );
|
||||||
|
|
||||||
|
add_action( 'admin_notices', function () {
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$source = WP_CONTENT_DIR . '/plugins/memcached/object-cache.php';
|
||||||
|
$target = WP_CONTENT_DIR . '/object-cache.php';
|
||||||
|
|
||||||
|
if ( ! file_exists( $source ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( file_exists( $target ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( class_exists( 'Memcache' ) || class_exists( 'Memcached' ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(
|
||||||
|
'<div class="notice notice-warning is-dismissible"><p>%s</p></div>',
|
||||||
|
'<strong>Настройка кеширования:</strong> Плагин Memcached Object Cache установлен, но PHP-расширение <code>memcache</code> не найдено.
|
||||||
|
Установите его на сервере (sudo apt install php-memcache), после чего drop-in скопируется автоматически.
|
||||||
|
<strong>Не активируйте плагин</strong> — это вызовет фатальную ошибку. Он работает как drop-in.'
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// 7. WP-CLI
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
||||||
|
|
||||||
/**
|
|
||||||
* Сброс версии кеша.
|
|
||||||
*/
|
|
||||||
WP_CLI::add_command( 'dekart cache-flush', function () {
|
WP_CLI::add_command( 'dekart cache-flush', function () {
|
||||||
my_cache_bump_version();
|
my_cache_bump_version();
|
||||||
WP_CLI::success( 'Cache flushed + version bumped.' );
|
WP_CLI::success( 'Cache flushed + version bumped.' );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
/**
|
|
||||||
* Установить drop-in Memcached Object Cache.
|
|
||||||
*
|
|
||||||
* Копирует object-cache.php из плагина memcached в wp-content/.
|
|
||||||
* Использовать ПОСЛЕ удаления Redis-плагина.
|
|
||||||
*/
|
|
||||||
WP_CLI::add_command( 'dekart cache-memcached', function () {
|
WP_CLI::add_command( 'dekart cache-memcached', function () {
|
||||||
$source = WP_CONTENT_DIR . '/plugins/memcached/object-cache.php';
|
$source = WP_CONTENT_DIR . '/plugins/memcached/object-cache.php';
|
||||||
$target = WP_CONTENT_DIR . '/object-cache.php';
|
$target = WP_CONTENT_DIR . '/object-cache.php';
|
||||||
@ -146,25 +188,29 @@ if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( file_exists( $target ) ) {
|
||||||
|
WP_CLI::success( 'Drop-in already exists at wp-content/object-cache.php' );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( ! class_exists( 'Memcache' ) && ! class_exists( 'Memcached' ) ) {
|
if ( ! class_exists( 'Memcache' ) && ! class_exists( 'Memcached' ) ) {
|
||||||
WP_CLI::warning( 'PHP memcache/memcached extension not found.' );
|
WP_CLI::warning( 'PHP memcache extension not found. Install it:' );
|
||||||
WP_CLI::line( 'Install it on your server first, then run this command again.' );
|
WP_CLI::line( ' sudo apt install php-memcache' );
|
||||||
WP_CLI::line( 'Debian/Ubuntu: sudo apt install php-memcache' );
|
WP_CLI::line( ' sudo systemctl restart php8.3-fpm' );
|
||||||
WP_CLI::line( 'After install, copy the drop-in manually:' );
|
WP_CLI::line( 'Then run this command again.' );
|
||||||
WP_CLI::line( " cp {$source} {$target}" );
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( copy( $source, $target ) ) {
|
if ( copy( $source, $target ) ) {
|
||||||
WP_CLI::success( 'Memcached drop-in installed to wp-content/object-cache.php' );
|
WP_CLI::success( 'Memcached drop-in installed to wp-content/object-cache.php' );
|
||||||
} else {
|
} else {
|
||||||
WP_CLI::error( 'Failed to copy drop-in. Check file permissions.' );
|
WP_CLI::error( 'Failed to copy drop-in. Check permissions.' );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// 6. ЛОГИРОВАНИЕ (dev only)
|
// 8. ЛОГИРОВАНИЕ
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
|
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user