felixarntz/theme-boilerplate

View on GitHub
inc/library/settings/class-setting.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php
/**
 * Super_Awesome_Theme_Setting class
 *
 * @package Super_Awesome_Theme
 * @license GPL-2.0-or-later
 * @link    https://super-awesome-author.org/themes/super-awesome-theme/
 */

/**
 * Class representing a theme setting.
 *
 * @since 1.0.0
 */
class Super_Awesome_Theme_Setting {

    /**
     * ID property name.
     *
     * @since 1.0.0
     */
    const PROP_ID = 'id';

    /**
     * Capability property name.
     *
     * @since 1.0.0
     */
    const PROP_CAPABILITY = 'capability';

    /**
     * Default property name.
     *
     * @since 1.0.0
     */
    const PROP_DEFAULT = 'default';

    /**
     * Validate callback property name.
     *
     * @since 1.0.0
     */
    const PROP_VALIDATE_CALLBACK = 'validate_callback';

    /**
     * Sanitize callback property name.
     *
     * @since 1.0.0
     */
    const PROP_SANITIZE_CALLBACK = 'sanitize_callback';

    /**
     * Parse callback property name.
     *
     * @since 1.0.0
     */
    const PROP_PARSE_CALLBACK = 'parse_callback';

    /**
     * Unique string identifier for the setting.
     *
     * @since 1.0.0
     * @var string
     */
    protected $id;

    /**
     * Capability required to edit this setting.
     *
     * @since 1.0.0
     * @var string|array
     */
    protected $capability;

    /**
     * The default value for the setting.
     *
     * @since 1.0.0
     * @var mixed
     */
    protected $default;

    /**
     * Validation callback for the setting's value.
     *
     * @since 1.0.0
     * @var callable
     */
    protected $validate_callback;

    /**
     * Sanitization callback for the setting's value in un-slashed form.
     *
     * @since 1.0.0
     * @var callable
     */
    protected $sanitize_callback;

    /**
     * Parse callback for the setting's value coming from the database.
     *
     * @since 1.0.0
     * @var callable
     */
    protected $parse_callback;

    /**
     * Constructor.
     *
     * Sets the setting definition.
     *
     * @since 1.0.0
     *
     * @param string $id   Unique string identifier for this setting.
     * @param array  $args Setting definition as $prop => $value pairs.
     */
    public function __construct( $id, array $args = array() ) {
        $this->id = (string) $id;

        $defaults = $this->get_defaults();
        foreach ( $defaults as $prop => $default_value ) {
            if ( array_key_exists( $prop, $args ) ) {
                $this->$prop = $args[ $prop ];
            } else {
                $this->$prop = $default_value;
            }
        }
    }

    /**
     * Gets the value for a setting property.
     *
     * @since 1.0.0
     *
     * @param string $prop Property name.
     * @return mixed Property value.
     *
     * @throws InvalidArgumentException Thrown when $prop is invalid.
     */
    final public function get_prop( $prop ) {
        $props = $this->get_props();

        if ( ! array_key_exists( $prop, $props ) ) {

            /* translators: 1: property name, 2: setting identifier */
            throw new InvalidArgumentException( sprintf( __( '%1$s is not a valid property of the %2$s setting.', 'super-awesome-theme' ), $prop, $this->id ) );
        }

        return $props[ $prop ];
    }

    /**
     * Gets the values for all setting properties.
     *
     * @since 1.0.0
     *
     * @return array Setting properties including ID as $prop => $value pairs.
     */
    final public function get_props() {
        $props = array( 'id' => $this->id );

        $default_props = array_keys( $this->get_defaults() );
        foreach ( $default_props as $prop ) {
            $props[ $prop ] = $this->$prop;
        }

        return $props;
    }

    /**
     * Gets the current value for the setting.
     *
     * @since 1.0.0
     *
     * @return mixed Current value for the setting, or the default value.
     */
    final public function get_value() {
        $value = get_theme_mod( $this->id, $this->default );

        return $this->parse_value( $value );
    }

    /**
     * Validates a value for the setting.
     *
     * @since 1.0.0
     *
     * @param WP_Error $validity Error object to add validation errors to.
     * @param mixed    $value    Value to validate.
     * @return WP_Error Error object with or without errors.
     */
    final public function validate_value( WP_Error $validity, $value ) {
        $validity = $this->default_validation_callback( $validity, $value );

        if ( null !== $this->validate_callback ) {
            $validity = call_user_func( $this->validate_callback, $validity, $value );
        }

        if ( is_wp_error( $validity ) ) {
            return $validity;
        }

        if ( ! $validity ) {
            return new WP_Error( 'invalid_value', __( 'Invalid value.', 'super-awesome-theme' ) );
        }

        return new WP_Error();
    }

    /**
     * Sanitizes a value for the setting.
     *
     * @since 1.0.0
     *
     * @param mixed $value Value to sanitize.
     * @return mixed Sanitized value.
     */
    final public function sanitize_value( $value ) {
        $value = $this->default_sanitization_callback( $value );

        if ( null !== $this->sanitize_callback ) {
            $value = call_user_func( $this->sanitize_callback, $value );
        }

        return $value;
    }

    /**
     * Parses a value for the setting.
     *
     * @since 1.0.0
     *
     * @param mixed $value Value to parse.
     * @return mixed Parsed value.
     */
    final public function parse_value( $value ) {
        $value = $this->default_parsing_callback( $value );

        if ( null !== $this->parse_callback ) {
            $value = call_user_func( $this->parse_callback, $value );
        }

        return $value;
    }

    /**
     * Performs default validation for a value for the setting.
     *
     * @since 1.0.0
     *
     * @param WP_Error $validity Error object to add validation errors to.
     * @param mixed    $value    Value to validate.
     * @return WP_Error Error object to add possible errors to.
     */
    protected function default_validation_callback( WP_Error $validity, $value ) {
        return $validity;
    }

    /**
     * Performs default sanitization for a value for the setting.
     *
     * @since 1.0.0
     *
     * @param mixed $value Value to sanitize.
     * @return mixed Sanitized value.
     */
    protected function default_sanitization_callback( $value ) {
        return $value;
    }

    /**
     * Performs default parsing for a value for the setting.
     *
     * @since 1.0.0
     *
     * @param mixed $value Value to parse.
     * @return mixed Parsed value.
     */
    protected function default_parsing_callback( $value ) {
        return $value;
    }

    /**
     * Gets the default setting definition properties to set.
     *
     * @since 1.0.0
     *
     * @return array Default setting definition as $prop => $default_value pairs. Each
     *               key present should have a class property of the same name. Defaults
     *               should be present for every setting property, even if the default
     *               is null.
     */
    protected function get_defaults() {
        return array(
            self::PROP_CAPABILITY        => 'edit_theme_options',
            self::PROP_DEFAULT           => false,
            self::PROP_VALIDATE_CALLBACK => null,
            self::PROP_SANITIZE_CALLBACK => null,
            self::PROP_PARSE_CALLBACK    => null,
        );
    }
}