robotstxt-ai-translator/includes/class-ai-translator-settings.php
2026-05-28 07:22:36 +00:00

223 lines
5.7 KiB
PHP

<?php
/**
* Settings management for the AI Translator plugin.
*
* @package ROBOTSTXT\AI_Translator
* @since 1.0.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'AI_Translator_Settings' ) ) {
/**
* Handles reading and writing the plugin settings in single-site and Multisite contexts.
*
* In Multisite, the network admin chooses between two modes:
* - "global" : a single configuration shared by every subsite.
* - "per-site" : each subsite stores its own configuration, with the network values
* acting as defaults when a subsite has not been configured yet.
*
* @since 1.0.0
*/
class AI_Translator_Settings {
/**
* Option key for site-level settings (single-site or per-site Multisite mode).
*
* @since 1.0.0
* @var string
*/
const OPTION_SITE = 'ai_translator_settings';
/**
* Sitemeta key for network-level settings (Multisite global mode and defaults).
*
* @since 1.0.0
* @var string
*/
const OPTION_NETWORK = 'ai_translator_settings';
/**
* Sitemeta key for the configuration mode in Multisite.
*
* @since 1.0.0
* @var string
*/
const OPTION_MODE = 'ai_translator_network_mode';
/**
* Default settings values.
*
* Boolean keys are coerced to bool on read/write; integer keys to int.
*
* @since 1.0.0
* @var array<string,bool|int>
*/
const DEFAULTS = array(
'translate_title' => true,
'translate_content' => true,
'translate_excerpt' => true,
'auto_translate_on_mlp_create' => false,
'request_timeout' => 60,
);
/**
* Returns the current configuration mode in Multisite.
*
* @since 1.0.0
*
* @return string Either 'global' or 'per-site'. Returns 'global' on single-site installs.
*/
public function get_network_mode() {
if ( ! is_multisite() ) {
return 'global';
}
$mode = get_site_option( self::OPTION_MODE, 'global' );
return in_array( $mode, array( 'global', 'per-site' ), true ) ? $mode : 'global';
}
/**
* Updates the Multisite configuration mode.
*
* @since 1.0.0
*
* @param string $mode Either 'global' or 'per-site'.
*
* @return bool True on success.
*/
public function update_network_mode( $mode ) {
if ( ! is_multisite() ) {
return false;
}
$mode = in_array( $mode, array( 'global', 'per-site' ), true ) ? $mode : 'global';
return (bool) update_site_option( self::OPTION_MODE, $mode );
}
/**
* Returns the effective settings for a given site, applying multisite mode rules.
*
* @since 1.0.0
*
* @param int|null $blog_id Optional blog ID. Defaults to the current site.
*
* @return array<string,bool|int> Settings array with typed values.
*/
public function get_settings( $blog_id = null ) {
if ( ! is_multisite() ) {
return $this->normalize( (array) get_option( self::OPTION_SITE, array() ) );
}
$mode = $this->get_network_mode();
if ( 'global' === $mode ) {
return $this->normalize( (array) get_site_option( self::OPTION_NETWORK, array() ) );
}
$network_defaults = $this->normalize( (array) get_site_option( self::OPTION_NETWORK, array() ) );
if ( null === $blog_id || get_current_blog_id() === (int) $blog_id ) {
$site_settings = get_option( self::OPTION_SITE, null );
} else {
switch_to_blog( (int) $blog_id );
$site_settings = get_option( self::OPTION_SITE, null );
restore_current_blog();
}
if ( null === $site_settings ) {
return $network_defaults;
}
return $this->normalize( array_merge( $network_defaults, (array) $site_settings ) );
}
/**
* Returns the raw network-level settings (used by the network admin form).
*
* @since 1.0.0
*
* @return array<string,bool|int>
*/
public function get_network_settings() {
return $this->normalize( (array) get_site_option( self::OPTION_NETWORK, array() ) );
}
/**
* Returns the raw site-level settings (used by the site admin form).
*
* @since 1.0.0
*
* @return array<string,bool|int>
*/
public function get_site_settings() {
return $this->normalize( (array) get_option( self::OPTION_SITE, array() ) );
}
/**
* Persists the network-level settings (Multisite only).
*
* @since 1.0.0
*
* @param array<string,bool|int> $settings Settings to store.
*
* @return bool True on success.
*/
public function update_network_settings( array $settings ) {
if ( ! is_multisite() ) {
return false;
}
return (bool) update_site_option( self::OPTION_NETWORK, $this->normalize( $settings ) );
}
/**
* Persists the site-level settings.
*
* @since 1.0.0
*
* @param array<string,bool|int> $settings Settings to store.
*
* @return bool True on success.
*/
public function update_site_settings( array $settings ) {
return (bool) update_option( self::OPTION_SITE, $this->normalize( $settings ) );
}
/**
* Normalises raw settings into a typed array matching the schema.
*
* Boolean keys are coerced to strict bool; integer keys to strict int.
* The DEFAULTS constant is the authoritative schema: any key not present
* there is silently dropped, and any missing key falls back to its default.
*
* @since 1.0.0
*
* @param array<int|string,mixed> $settings Raw settings.
*
* @return array<string,bool|int>
*/
private function normalize( array $settings ) {
$normalized = array();
foreach ( self::DEFAULTS as $key => $default ) {
if ( array_key_exists( $key, $settings ) ) {
if ( is_int( $default ) ) {
$normalized[ $key ] = (int) $settings[ $key ];
} else {
$normalized[ $key ] = (bool) $settings[ $key ];
}
} else {
$normalized[ $key ] = $default;
}
}
return $normalized;
}
}
}