284 lines
5.7 KiB
PHP
284 lines
5.7 KiB
PHP
<?php
|
|
/**
|
|
* @package Polylang
|
|
*/
|
|
|
|
namespace WP_Syntex\Polylang\Options;
|
|
|
|
use WP_Error;
|
|
use WP_Term;
|
|
use WP_Syntex\Polylang\Options\Options;
|
|
|
|
defined( 'ABSPATH' ) || exit;
|
|
|
|
/**
|
|
* Class defining a single option.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @phpstan-type SchemaType 'string'|'null'|'number'|'integer'|'boolean'|'array'|'object'
|
|
* @phpstan-type Schema array{
|
|
* type: SchemaType
|
|
* }
|
|
*/
|
|
abstract class Abstract_Option {
|
|
/**
|
|
* Option value.
|
|
*
|
|
* @var mixed
|
|
*/
|
|
private $value;
|
|
|
|
/**
|
|
* Cached option JSON schema.
|
|
*
|
|
* @var array|null
|
|
*
|
|
* @phpstan-var Schema|null
|
|
*/
|
|
private $schema;
|
|
|
|
/**
|
|
* Validation and sanitization errors.
|
|
*
|
|
* @var WP_Error
|
|
*/
|
|
protected $errors;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @param mixed $value Optional. Option value.
|
|
*/
|
|
public function __construct( $value = null ) {
|
|
$this->errors = new WP_Error();
|
|
|
|
if ( ! isset( $value ) ) {
|
|
$this->value = $this->get_default();
|
|
return;
|
|
}
|
|
|
|
$value = rest_sanitize_value_from_schema( $this->prepare( $value ), $this->get_data_structure(), static::key() );
|
|
|
|
if ( ! is_wp_error( $value ) ) {
|
|
$this->value = $value;
|
|
} else {
|
|
$this->value = $this->get_default();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns option key.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @return string
|
|
*
|
|
* @phpstan-return non-falsy-string
|
|
*/
|
|
abstract public static function key(): string;
|
|
|
|
/**
|
|
* Sets option's value if valid, does nothing otherwise.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @param mixed $value Value to set.
|
|
* @param Options $options All options.
|
|
* @return bool True if the value has been assigned. False in case of errors.
|
|
*/
|
|
public function set( $value, Options $options ): bool {
|
|
$this->errors = new WP_Error(); // Reset errors.
|
|
$value = $this->prepare( $value );
|
|
$is_valid = rest_validate_value_from_schema( $value, $this->get_data_structure(), static::key() );
|
|
|
|
if ( is_wp_error( $is_valid ) ) {
|
|
// Blocking validation error.
|
|
$this->errors->merge_from( $is_valid );
|
|
return false;
|
|
}
|
|
|
|
$value = $this->sanitize( $value, $options );
|
|
|
|
if ( is_wp_error( $value ) ) {
|
|
// Blocking sanitization error.
|
|
$this->errors->merge_from( $value );
|
|
return false;
|
|
}
|
|
|
|
$this->value = $value;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns option's value.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public function &get() {
|
|
return $this->value;
|
|
}
|
|
|
|
/**
|
|
* Sets default option value.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @return mixed The new value.
|
|
*/
|
|
public function reset() {
|
|
$this->value = $this->get_default();
|
|
return $this->value;
|
|
}
|
|
|
|
/**
|
|
* Returns JSON schema of the option.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @return array The schema.
|
|
*
|
|
* @phpstan-return Schema
|
|
*/
|
|
public function get_schema(): array {
|
|
if ( is_array( $this->schema ) ) {
|
|
return $this->schema;
|
|
}
|
|
|
|
$this->schema = array_merge(
|
|
array(
|
|
'description' => $this->get_description(),
|
|
'default' => $this->get_default(),
|
|
),
|
|
$this->get_data_structure()
|
|
);
|
|
|
|
return $this->schema;
|
|
}
|
|
|
|
/**
|
|
* Returns non-blocking sanitization errors.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @return WP_Error
|
|
*/
|
|
public function get_errors(): WP_Error {
|
|
return $this->errors;
|
|
}
|
|
|
|
/**
|
|
* Prepares a value before validation.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @param mixed $value Value to format.
|
|
* @return mixed
|
|
*/
|
|
protected function prepare( $value ) {
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Sanitizes option's value, can be overridden for specific cases not handled by `rest_sanitize_value_from_schema()`.
|
|
* Can populate the `$errors` property with blocking and non-blocking errors: in case of non-blocking errors,
|
|
* the value is sanitized and can be stored.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @param mixed $value Value to sanitize.
|
|
* @param Options $options All options.
|
|
* @return mixed The sanitized value. An instance of `WP_Error` in case of blocking error.
|
|
*/
|
|
protected function sanitize( $value, Options $options ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
|
return rest_sanitize_value_from_schema( $value, $this->get_data_structure(), static::key() );
|
|
}
|
|
|
|
/**
|
|
* Returns the default value.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @return mixed
|
|
*/
|
|
abstract protected function get_default();
|
|
|
|
/**
|
|
* Returns the JSON schema part specific to this option.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @return array Partial schema.
|
|
*
|
|
* @phpstan-return array{type: SchemaType}
|
|
*/
|
|
abstract protected function get_data_structure(): array;
|
|
|
|
/**
|
|
* Returns the description used in the JSON schema.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @return string
|
|
*/
|
|
abstract protected function get_description(): string;
|
|
|
|
/**
|
|
* Returns a list of language terms.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @return array
|
|
*
|
|
* @phpstan-return list<WP_Term>
|
|
*/
|
|
protected function get_language_terms(): array {
|
|
$language_terms = get_terms(
|
|
array(
|
|
'taxonomy' => 'language',
|
|
'hide_empty' => false,
|
|
)
|
|
);
|
|
return is_array( $language_terms ) ? $language_terms : array();
|
|
}
|
|
|
|
/**
|
|
* Adds a non-blocking error warning about unknown language slugs.
|
|
*
|
|
* @since 3.7
|
|
*
|
|
* @param array $language_slugs List of language slugs.
|
|
* @return void
|
|
*/
|
|
protected function add_unknown_languages_warning( array $language_slugs ): void {
|
|
if ( 1 === count( $language_slugs ) ) {
|
|
/* translators: %s is a language slug. */
|
|
$message = __( 'The language %s is unknown and has been discarded.', 'polylang' );
|
|
} else {
|
|
/* translators: %s is a list of language slugs. */
|
|
$message = __( 'The languages %s are unknown and have been discarded.', 'polylang' );
|
|
}
|
|
|
|
$this->errors->add(
|
|
sprintf( 'pll_unknown_%s_languages', static::key() ),
|
|
sprintf(
|
|
$message,
|
|
wp_sprintf_l(
|
|
'%l',
|
|
array_map(
|
|
function ( $slug ) {
|
|
return "<code>{$slug}</code>";
|
|
},
|
|
$language_slugs
|
|
)
|
|
)
|
|
),
|
|
'warning'
|
|
);
|
|
}
|
|
}
|