Add PSR HTTP Message Interfaces and Dependencies

- Implemented StreamInterface, UploadedFileInterface, and UriInterface as per PSR standards.
- Added getallheaders function to retrieve HTTP headers in a compatible manner.
- Included LICENSE files for ralouphie/getallheaders and symfony/deprecation-contracts.
- Introduced function for triggering deprecation notices in Symfony.
This commit is contained in:
2025-12-28 12:44:00 +01:00
parent cf600ae727
commit cd264483f8
410 changed files with 60841 additions and 16 deletions

View File

@@ -0,0 +1,166 @@
<?php
/**
* Class ATFPP\AI_Translate\Services\Options\Option_Encrypter
*
* @since 0.1.0
* @package ai-services
*/
namespace ATFPP\AI_Translate\Services\Options;
use ATFPP\AI_Translate\Services\Util\Data_Encryption;
/**
* Class that allows for options to be encrypted when stored in the database as well as decrypted when retrieved.
*
* @since 0.1.0
*/
final class Option_Encrypter {
const ENCRYPTION_PREFIX = 'enc::';
/**
* The data encryption instance.
*
* @since 0.1.0
* @var Data_Encryption
*/
private $data_encryption;
/**
* Constructor.
*
* @since 0.1.0
*
* @param Data_Encryption $data_encryption The data encryption instance.
*/
public function __construct( Data_Encryption $data_encryption ) {
$this->data_encryption = $data_encryption;
}
/**
* Adds relevant hooks to handle encryption and decryption of the given option.
*
* @since 0.1.0
*
* @param string $option_slug The option to use encryption with.
*/
public function add_encryption_hooks( string $option_slug ): void {
add_filter( "sanitize_option_{$option_slug}", array( $this, 'encrypt_option' ), 9999, 2 ); // Encrypt late.
add_filter( "option_{$option_slug}", array( $this, 'decrypt_option' ), -9999, 2 ); // Decrypt early.
}
/**
* Checks if the given option has encryption enabled.
*
* @since 0.1.0
*
* @param string $option_slug The identifier/name of the option.
* @return bool True if the option has encryption enabled, false otherwise.
*/
public function has_encryption( string $option_slug ): bool {
return (
has_filter( "sanitize_option_{$option_slug}", array( $this, 'encrypt_option' ) ) &&
has_filter( "option_{$option_slug}", array( $this, 'decrypt_option' ) )
);
}
/**
* Encrypts the given option value.
*
* @since 0.1.0
*
* @param mixed $value The option value to encrypt.
* @param string $option_slug The identifier/name of the option.
* @return string Encrypted option value.
*/
public function encrypt_option( $value, string $option_slug ): string {
// Do not encrypt if the value is empty.
if ( '' === $value ) {
return $value;
}
// Bail if the value is already encrypted.
if ( is_string( $value ) && str_starts_with( $value, self::ENCRYPTION_PREFIX ) ) {
return $value;
}
$encrypted = $this->data_encryption->encrypt( maybe_serialize( $value ) );
// If encryption fails, trigger a warning but continue with the unencrypted value. Better not to lose data.
if ( ! $encrypted ) {
$this->trigger_error(
__METHOD__,
sprintf(
/* translators: %s: Option slug */
__( 'Failed to encrypt the value for the option "%s".', 'ai-services' ),
$option_slug
)
);
return $value;
}
return self::ENCRYPTION_PREFIX . $encrypted;
}
/**
* Decrypts the given option value.
*
* @since 0.1.0
*
* @param mixed $value The option value to decrypt.
* @param string $option_slug The identifier/name of the option.
* @return mixed Decrypted option value.
*/
public function decrypt_option( $value, string $option_slug ) {
// Bail if the value is already decrypted.
if ( ! is_string( $value ) || ! str_starts_with( $value, self::ENCRYPTION_PREFIX ) ) {
return $value;
}
$decrypted = $this->data_encryption->decrypt( substr( $value, strlen( self::ENCRYPTION_PREFIX ) ) );
// If decryption fails, trigger a warning and return an empty string.
if ( ! $decrypted ) {
$this->trigger_error(
__METHOD__,
sprintf(
/* translators: %s: Option slug */
__( 'Failed to decrypt the value for the option "%s".', 'ai-services' ),
$option_slug
)
);
return '';
}
return maybe_unserialize( $decrypted );
}
/**
* Triggers an error, if WP_DEBUG is enabled.
*
* @since 0.1.0
*
* @param string $function_name The name of the function that triggered the error.
* @param string $message The message explaining the error.
* @param int $error_level Optional. The designated error type for this error.
* Only works with E_USER family of constants. Default E_USER_NOTICE.
*/
private function trigger_error( string $function_name, string $message, int $error_level = E_USER_NOTICE ): void {
// The wp_trigger_error() function was only added in WordPress 6.4, so this is a minimal shim.
if ( ! function_exists( 'wp_trigger_error' ) ) {
if ( ! WP_DEBUG ) {
return;
}
if ( ! empty( $function_name ) ) {
$message = sprintf( '%s(): %s', $function_name, $message );
}
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
trigger_error( esc_html( $message ), $error_level );
return;
}
// @phpstan-ignore-next-line
wp_trigger_error( $function_name, $message, $error_level );
}
}