<?php
/**
* Settings save service.
*
* @package PoweredCache
*/
namespace PoweredCache;
use PoweredCache\Async\CachePreloader;
use PoweredCache\Async\CachePurger;
use const PoweredCache\Constants\PURGE_CACHE_CRON_NAME;
/**
* Persists settings and runs post-save side effects.
*
* @since 4.0.0
*/
class SettingsSaveService {
/**
* Settings repository.
*
* @var SettingsRepository
*/
private $repository;
/**
* Whether settings use network storage.
*
* @var bool
*/
private $network_wide;
/**
* Constructor.
*
* @param SettingsRepository|null $repository Settings repository.
* @param bool $network_wide Whether settings use network storage.
*/
public function __construct( ?SettingsRepository $repository = null, $network_wide = false ) {
$this->network_wide = (bool) $network_wide;
$this->repository = null === $repository ? SettingsRepository::factory( $this->network_wide ) : $repository;
}
/**
* Create a service instance.
*
* @param SettingsRepository|null $repository Settings repository.
* @param bool $network_wide Whether settings use network storage.
*
* @return SettingsSaveService
*/
public static function factory( ?SettingsRepository $repository = null, $network_wide = false ) {
return new self( $repository, $network_wide );
}
/**
* Save settings and run post-save hooks.
*
* @param array $settings Settings payload.
* @param array|null $old_settings Previous settings.
*
* @return array Saved settings.
*/
public function save( array $settings, ?array $old_settings = null ) {
if ( null === $old_settings ) {
$old_settings = $this->repository->all();
}
$settings = SettingsSchema::enforce_editable( $settings, $old_settings );
$this->repository->save( $settings );
$settings = $this->repository->all();
Config::factory()->save_configuration( $settings, $this->network_wide );
$this->handle_side_effects( $old_settings, $settings );
return $settings;
}
/**
* Run post-save side effects.
*
* @param array $old_settings Previous settings.
* @param array $settings Current settings.
*/
public function handle_side_effects( array $old_settings, array $settings ) {
if ( isset( $settings['object_cache'], $old_settings['object_cache'] ) && $old_settings['object_cache'] !== $settings['object_cache'] ) {
wp_cache_flush();
}
if ( ! empty( $old_settings['dev_mode'] ) && empty( $settings['dev_mode'] ) ) {
wp_cache_flush();
}
if ( ! empty( $old_settings['enable_cache_preload'] ) && empty( $settings['enable_cache_preload'] ) ) {
$this->cancel_preloading();
}
if ( empty( $old_settings['enable_cache_preload'] ) && ! empty( $settings['enable_cache_preload'] ) && ! empty( $settings['enable_page_cache'] ) ) {
$this->start_preloading();
}
if (
! empty( $old_settings['enable_cache_preload'] )
&& ! empty( $settings['enable_cache_preload'] )
&& ! empty( $old_settings['enable_page_cache'] )
&& ! empty( $settings['enable_page_cache'] )
&& $this->preload_source_settings_changed( $old_settings, $settings )
) {
$this->restart_preloading();
}
if ( ! empty( $old_settings['async_cache_cleaning'] ) && empty( $settings['async_cache_cleaning'] ) ) {
$this->cancel_async_cache_cleaning();
}
if ( ! empty( $old_settings['enable_page_cache'] ) && empty( $settings['enable_page_cache'] ) ) {
\PoweredCache\Utils\clean_site_cache_dir();
if ( ! empty( $settings['enable_cache_preload'] ) ) {
$this->cancel_preloading();
}
}
if (
empty( $old_settings['enable_page_cache'] )
&& ! empty( $settings['enable_page_cache'] )
&& ! empty( $old_settings['enable_cache_preload'] )
&& ! empty( $settings['enable_cache_preload'] )
) {
$this->start_preloading();
}
if ( ! empty( $old_settings['rewrite_file_optimizer'] ) && empty( $settings['rewrite_file_optimizer'] ) ) {
\PoweredCache\Utils\clean_site_cache_dir();
}
if ( isset( $old_settings['cache_timeout'], $settings['cache_timeout'] ) && $old_settings['cache_timeout'] !== $settings['cache_timeout'] ) {
$timestamp = wp_next_scheduled( PURGE_CACHE_CRON_NAME );
wp_unschedule_event( $timestamp, PURGE_CACHE_CRON_NAME );
}
/**
* Fires after saving configurations.
*
* @hook powered_cache_settings_saved
*
* @param {array} $old_settings Old settings.
* @param {array} $settings New settings.
*
* @since 1.0
*/
do_action( 'powered_cache_settings_saved', $old_settings, $settings );
}
/**
* Cancel preloading process when preload is disabled.
*/
protected function cancel_preloading() {
\PoweredCache\Utils\log( 'Cancel preload process - Settings toggle' );
$cache_preloader = CachePreloader::factory();
$cache_preloader->delete_all();
}
/**
* Kick-start preloading process when preload is enabled.
*/
protected function start_preloading() {
\PoweredCache\Utils\log( 'Enable Preloader - Settings toggle' );
Preloader::factory()->setup_preload_queue();
Preloader::factory()->dispatch_preload_queue();
}
/**
* Rebuild the preload queue after source settings change.
*/
protected function restart_preloading() {
\PoweredCache\Utils\log( 'Refresh Preloader - Source settings changed' );
$this->start_preloading();
}
/**
* Cancel async cache purging processes.
*/
protected function cancel_async_cache_cleaning() {
\PoweredCache\Utils\log( 'Cancel CachePurger process' );
$cache_purger = CachePurger::factory();
$cache_purger->cancel_process();
}
/**
* Whether settings that populate the preload queue changed.
*
* @param array $old_settings Previous settings.
* @param array $settings Current settings.
*
* @return bool
*/
private function preload_source_settings_changed( array $old_settings, array $settings ) {
$preload_sources = array(
'preload_homepage',
'preload_public_posts',
'preload_public_tax',
'enable_sitemap_preload',
'preload_sitemap',
);
foreach ( $preload_sources as $source ) {
$old_value = isset( $old_settings[ $source ] ) ? $old_settings[ $source ] : null;
$new_value = isset( $settings[ $source ] ) ? $settings[ $source ] : null;
if ( $old_value !== $new_value ) {
return true;
}
}
return false;
}
}