Вопрос или проблема
Я использую этот код, чтобы включить обновление плагина с административной страницы WordPress.
add_filter('plugins_api', 'pud_plugin_info', 20, 3 );
add_filter('update_plugins_my_domain_url', 'pud_update', 10, 4);
add_filter('plugin_auto_update_setting_html', 'pud_plugin_auto_update_setting_html', 10, 3 );
add_action('in_plugin_update_message-plugin-folder/my_plugin.php', 'pud_display_update_message', 10, 2 );
function pud_plugin_auto_update_setting_html($html, $plugin_file, $plugin_data) {
if ($plugin_file == 'plugin-folder/my_plugin.php') {
if(empty($plugin_data['package'])){
$html = sprintf(__("<span style="color:red;">%s</span>", TEXTDOMAIN), 'Автообновления отключены');
}
}
return $html;
}
function pud_display_update_message( $plugin_info_array, $plugin_info_object ) {
if(empty($plugin_info_array['package'])) {
//нет обновлений
}
}
function pud_request(){
$url="my-website-url";
$response = wp_remote_post($url, array(
'method' => 'POST',
'timeout' => 10,
'headers' => array('Accept' => 'application/json'),
'body' => array(
'token' => $token,
'plugin' => plugin_id,
'website' => get_url()
)
));
if(is_wp_error($response) || 200 !== wp_remote_retrieve_response_code( $response ) || empty( wp_remote_retrieve_body( $response )) ){
return false;
}else{
$remote = json_decode( wp_remote_retrieve_body( $response ) );
}
return $remote;
}
}
function pud_plugin_info( $res, $action, $args ) {
if('plugin_information' === $action && $args->slug == PLUGIN_SLUG) {
$remote = pud_request();
if( ! $remote ) {
return $res;
}
$res = new stdClass();
$res->name = $remote->name;
$res->slug = $remote->slug;
$res->version = $remote->version;
$res->tested = $remote->tested;
$res->requires = $remote->requires;
$res->author = $remote->author;
$res->author_profile = $remote->author_profile;
$res->download_link = $remote->download_url;
$res->trunk = $remote->download_url;
$res->requires_php = $remote->requires_php;
$res->last_updated = $remote->last_updated;
$res->package = $remote->package;
$res->sections = array(
'description' => $remote->sections->description,
'installation' => $remote->sections->installation,
'changelog' => $remote->sections->changelog
);
if( ! empty( $remote->banners ) ) {
$res->banners = array(
'low' => $remote->banners->low,
'high' => $remote->banners->high
);
}
}
return $res;
}
function pud_update($update, $plugin_data, $plugin_file, $locales) {
$remote = pud_request();
if($remote
&& (float)PLUGIN_VERSION < (float)$remote->version
&& (float)$remote->requires <= (float)get_bloginfo('version')
&& (float)$remote->requires_php < (float)PHP_VERSION ) {
if($remote->download_url && !empty($remote->download_url)){
$remote->package = $remote->download_url;
}
}
return $remote;
}
Это работает хорошо, однако, похоже, есть некоторая кэшировка на стороне WordPress (что иногда показывает, что обновления недоступны, даже если я обновляю страницу плагина), и только когда я добавляю этот код, тогда он сразу показывает, что обновления доступны.
add_action('init', function(){
delete_transient( 'update_plugins' );
delete_site_transient( 'update_plugins' );
});
Однако использование этого кода, насколько я знаю, не рекомендуется, и я могу заметить, что это значительно замедляет админку WordPress.
Каков лучший способ убедиться, что обновления всегда отображаются и не кэшируются?
Ответ или решение
Для решения проблемы обновления плагинов WordPress важно понять, как работает механизм кэширования обновлений. WordPress использует транзиенты (transients) для временного хранения информации о доступных обновлениях плагинов, чтобы снизить нагрузку на серверы и ускорить время загрузки админпанели. Ваша задача заключается в том, чтобы обеспечить своевременное обновление этой информации без значительной деградации производительности.
Теория
Транзиенты (Transients) в WordPress – это механизм временного хранения данных в базе данных для улучшения производительности. Они используются для хранения информации, которую периодически необходимо извлекать и обновлять. Например, информация об обновлениях плагинов хранится в полях update_plugins
и update_plugins
(для мультисайтов). При каждом посещении страницы плагинов WordPress не запрашивает информацию о новых версиях на удалённом сервере, а использует кешированные данные, хранящиеся в этих транзиентах.
Благодаря этому архитектурному решению серверы не перегружаются частыми запросами, а пользователи получают быстрый отклик на действия в админпанели. Однако в некоторых случаях, как в вашем, когда обновления не видны моментально, это может вызвать неудобства.
Примеры
Вы упомянули, что для удаления транзиентов вы используете следующий код:
add_action('init', function(){
delete_transient('update_plugins');
delete_site_transient('update_plugins');
});
Этот код запускается на каждом init
, удаляя кешированные данные о плагинах. Хотя это гарантировано решит проблему с показом свежих обновлений, он также увеличит количество запросов к серверам, негативно влияя на производительность. Следовательно, это может стать причиной замедления работы админпанели.
Применение
Лучшим решением будет оптимизация процесса вызова обновлений, сохраняя баланс между производительностью и актуальностью данных. Рассмотрим несколько техник, которые помогут улучшить обработку обновлений без разрушительных воздействий.
-
Увеличение интервала проверки обновлений: Вы можете управлять частотой обновлений, изменив периодичность крона. По умолчанию включает в свою работу
wp_update_plugins()
домашним заданием, его можно настроить через фильтры.add_filter('auto_update_plugin', '__return_true');
-
Ручной запуск обновлений: При необходимости вы можете принудительно вызывать обновление. Это может быть удобно, если администратор хочет моментально получить актуальные обновления, вызывая функцию только при посещении страницы администрирования плагинов.
function force_check_for_updates() { if (is_admin() && current_user_can('update_plugins')) { wp_update_plugins(); } } add_action('admin_init', 'force_check_for_updates');
-
Кастомизация через AJAX: Вы можете реализовать механизм, который по запросу будет удалять транзиенты и запускать проверку через AJAX. Это позволит обновлять информацию только по требованию.
add_action('wp_ajax_refresh_plugin_updates', 'refresh_plugin_updates'); function refresh_plugin_updates() { // Удаляем старые транзиенты delete_transient('update_plugins'); delete_site_transient('update_plugins'); // Запускаем проверку обновлений wp_update_plugins(); wp_send_json_success('Обновления проверены.'); }
Затем на стороне клиента можно реализовать кнопку, которая будет запускать эту проверку через AJAX.
-
Обработка ошибок и логирование: Чтобы избежать лишних запросов к серверу, используйте логирование или обработку ошибок для диагностики проблем с получением данных об обновлениях. Это обеспечит понимание и устранение проблем при неправильной настройке.
Учитывая вышеперечисленные методы, вы сможете управлять и улучшать механизм обновлений плагинов с минимальными потерями производительности. Главное – избегать частого удаления транзиентов через init
, при этом может помочь более целевой подход к извлечению обновлений.