shkola/wp-content/mu-plugins/object-cache-bootstrap.php
Dekart Deploy Bot 0bb005339c fix: remove auto-copy memcached drop-in (prevents broken HTML on prod)
- dekart_try_install_memcached_dropin() removed — no more auto-copy
  on plugins_loaded (causes PHP errors if memcached server not running)
- Admin notice shows: 'Install manually' when server is reachable,
  'Start Memcached server' when extension installed but no connect,
  'Install PHP extension' when missing
- Plugin action link shows 'install manually' instead of 'Activate'
- WP-CLI: wp dekart cache-memcached still works for manual install
2026-07-17 18:07:44 +00:00

227 lines
8.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* MU-Plugin: Object Cache Bootstrap
*
* Автоопределение backend кеширования + versioned cache + автоинвалидация.
* Работает с любым 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
* @version 2.1
*/
// ============================================================
// 1. КОНСТАНТЫ ДЛЯ ПЛАГИНОВ
// ============================================================
if ( ! defined( 'WP_REDIS_HOST' ) ) {
define( 'WP_REDIS_HOST', '127.0.0.1' );
}
if ( ! defined( 'WP_REDIS_PORT' ) ) {
define( 'WP_REDIS_PORT', 6379 );
}
if ( ! defined( 'WP_REDIS_DATABASE' ) ) {
define( 'WP_REDIS_DATABASE', 0 );
}
// ============================================================
// 2. АВТООПРЕДЕЛЕНИЕ BACKEND
// ============================================================
function dekart_detect_cache_backend(): string {
if ( class_exists( 'Memcache' ) || class_exists( 'Memcached' ) ) {
$sock = @fsockopen( '127.0.0.1', 11211, $errno, $errstr, 0.5 );
if ( $sock ) {
fclose( $sock );
return 'memcached';
}
}
if ( class_exists( 'Predis\Client' ) ) {
$sock = @fsockopen( '127.0.0.1', 6379, $errno, $errstr, 0.5 );
if ( $sock ) {
fclose( $sock );
return 'redis';
}
}
if ( file_exists( WP_CONTENT_DIR . '/object-cache.php' ) ) {
return 'dropin-no-connection';
}
return 'none';
}
// ============================================================
// 3. VERSIONED CACHE KEY
// ============================================================
function my_cache_version(): int {
return (int) get_option( 'my_cache_version', 1 );
}
function my_cache_key( string $key ): string {
return 'v:' . my_cache_version() . ':' . $key;
}
// ============================================================
// 4. ИНВАЛИДАЦИЯ КЕША
// ============================================================
function my_cache_bump_version(): void {
static $running = false;
if ( $running ) {
return;
}
$running = true;
wp_cache_flush();
$v = my_cache_version();
update_option( 'my_cache_version', $v + 1, false );
$running = false;
}
add_action( 'update_option', function ( $option ) {
if ( str_starts_with( $option, 'branch_' ) ) {
my_cache_bump_version();
}
}, 10, 1 );
add_action( 'save_post', 'my_cache_bump_version' );
add_action( 'carbon_fields_post_meta_container_saved', 'my_cache_bump_version' );
// ============================================================
// 5. АДМИН-НОТИС + БЛОКИРОВКА АКТИВАЦИИ MEMCACHED
// ============================================================
/**
* Убрать ссылку "Активировать" у плагина Memcached Object Cache.
* Плагин — только источник object-cache.php, активация вызывает фатальную ошибку.
*/
add_filter( 'plugin_action_links_memcached/object-cache.php', function ( $actions ) {
unset( $actions['activate'] );
$actions['info'] = '<span style="color:#999">⚠ установите вручную</span>';
return $actions;
} );
// ============================================================
// 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; // drop-in уже стоит
}
if ( class_exists( 'Memcache' ) || class_exists( 'Memcached' ) ) {
$conn = @fsockopen( '127.0.0.1', 11211, $errno, $errstr, 0.5 );
if ( $conn ) {
fclose( $conn );
// Всё готово — можно установить вручную
printf(
'<div class="notice notice-info is-dismissible"><p>%s</p></div>',
'<strong>Кеширование:</strong> Memcached доступен. Установите drop-in командой:
<code>cp ' . esc_html( str_replace( ABSPATH, '', $source ) ) . ' ' . esc_html( str_replace( ABSPATH, '', $target ) ) . '</code>
или через WP-CLI: <code>wp dekart cache-memcached</code>'
);
return;
}
// Есть расширение, но сервер не отвечает
printf(
'<div class="notice notice-warning is-dismissible"><p>%s</p></div>',
'<strong>Кеширование:</strong> PHP-расширение Memcache установлено, но сервер Memcached (127.0.0.1:11211) не отвечает.
Запустите Memcached на сервере или обратитесь в хостинг.'
);
return;
}
printf(
'<div class="notice notice-warning is-dismissible"><p>%s</p></div>',
'<strong>Кеширование:</strong> Плагин Memcached Object Cache установлен, но PHP-расширение <code>memcache</code> не найдено.
Установите его на сервере (через панель хостинга: PHP → Расширения → memcache).
<strong>Не активируйте плагин</strong> — это вызовет фатальную ошибку. Он работает как drop-in.'
);
} );
// ============================================================
// 7. WP-CLI
// ============================================================
if ( defined( 'WP_CLI' ) && WP_CLI ) {
WP_CLI::add_command( 'dekart cache-flush', function () {
my_cache_bump_version();
WP_CLI::success( 'Cache flushed + version bumped.' );
} );
WP_CLI::add_command( 'dekart cache-memcached', function () {
$source = WP_CONTENT_DIR . '/plugins/memcached/object-cache.php';
$target = WP_CONTENT_DIR . '/object-cache.php';
if ( ! file_exists( $source ) ) {
WP_CLI::error( 'Memcached Object Cache plugin not installed. Run: wp plugin install memcached' );
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' ) ) {
WP_CLI::warning( 'PHP memcache extension not found. Install it:' );
WP_CLI::line( ' sudo apt install php-memcache' );
WP_CLI::line( ' sudo systemctl restart php8.3-fpm' );
WP_CLI::line( 'Then run this command again.' );
return;
}
if ( copy( $source, $target ) ) {
WP_CLI::success( 'Memcached drop-in installed to wp-content/object-cache.php' );
} else {
WP_CLI::error( 'Failed to copy drop-in. Check permissions.' );
}
} );
}
// ============================================================
// 8. ЛОГИРОВАНИЕ
// ============================================================
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
add_action( 'init', function () {
$b = dekart_detect_cache_backend();
if ( 'none' === $b ) {
error_log( '[Object Cache] WARNING: No cache backend available.' );
}
}, 0 );
}