refactor: prove new settings approach

This commit is contained in:
Ben Goldsworthy 2021-05-17 12:56:22 +01:00
parent b98f327aad
commit 7135811d15
11 changed files with 960 additions and 158 deletions

View file

@ -157,6 +157,7 @@ class Core {
* @return void
*/
private function load_dependencies() {
require_once plugin_dir_path( __DIR__ ) . 'includes/class-settings.php';
/**
* The class responsible for orchestrating the actions and filters of the
@ -175,7 +176,6 @@ class Core {
*/
require_once plugin_dir_path( __DIR__ ) . 'includes/class-config.php';
require_once plugin_dir_path( __DIR__ ) . 'includes/class-convert.php';
require_once plugin_dir_path( __DIR__ ) . 'includes/class-settings.php';
require_once plugin_dir_path( __DIR__ ) . 'includes/class-template.php';
/**

View file

@ -1,6 +1,6 @@
<?php // phpcs:disable Squiz.Commenting.FileComment.Missing
/**
* File providing the `Setting` class.
* File providing the `Settings` class.
*
* @package footnotes
* @since 1.5.0
@ -19,6 +19,8 @@ namespace footnotes\includes;
*/
require_once plugin_dir_path( __DIR__ ) . 'includes/class-convert.php';
use footnotes\includes\settings\GeneralSettingsSection;
/**
* Class defining configurable plugin settings.
*
@ -1104,15 +1106,16 @@ class Settings {
const FOOTNOTE_SECTION_SHORTCODE = 'footnotes_inputfield_section_shortcode';
/**
* Contains all Settings Container names.
* Contains all Settings option group slugs.
*
* These are the storage container names, one per dashboard tab.
* Each option group relates to a single tab on the admin. dashboard.
*
* @var string[]
*
* @since 1.5.0
* @since 2.8.0 Renamed from `container` to `option_groups`.
*/
private array $container = array(
private array $option_groups = array(
'footnotes_storage',
'footnotes_storage_custom',
'footnotes_storage_expert',
@ -1129,7 +1132,7 @@ class Settings {
*
* @var (string|int)[]
*/
private array $default = array(
private array $default_settings = array(
// General settings.
'footnotes_storage' => array(
@ -1164,7 +1167,21 @@ class Settings {
self::FOOTNOTES_BACKLINK_TOOLTIP_TEXT => 'Alt+ ←',
// Reference container.
self::REFERENCE_CONTAINER_NAME => 'References',
self::REFERENCE_CONTAINER_NAME => array(
'title' => 'Reference container title',
'setting_args' => array (
'type' => 'string',
'description' => 'The title of the reference container',
'default' => 'References',
),
'field_args' => array (
'name' => self::REFERENCE_CONTAINER_NAME,
'label_for' => self::REFERENCE_CONTAINER_NAME,
'type' => 'text',
'value' => 'References',
'description' => 'The title of the reference container',
),
),
self::REFERENCE_CONTAINER_LABEL_ELEMENT => 'p',
self::REFERENCE_CONTAINER_LABEL_BOTTOM_BORDER => 'yes',
self::REFERENCE_CONTAINER_COLLAPSE => 'no',
@ -1281,7 +1298,7 @@ class Settings {
'footnotes_storage_expert' => array(
// WordPress hooks with priority level.
self::EXPERT_LOOKUP_THE_TITLE => '',
self::EXPERT_LOOKUP_THE_TITLE => "",
self::EXPERT_LOOKUP_THE_TITLE_PRIORITY_LEVEL => PHP_INT_MAX,
self::EXPERT_LOOKUP_THE_CONTENT => 'checked',
@ -1319,7 +1336,10 @@ class Settings {
* @since 1.5.0
* @todo Create `PreferencesSet` class.
*/
private array $settings = array();
public array $settings = array();
public GeneralSettingsSection $general_settings;
/**********************************************************************
* SETTINGS STORAGE.
**********************************************************************/
@ -1336,7 +1356,11 @@ class Settings {
* @since 1.5.0
*/
private function __construct() {
$this->load_all();
$this->load_options();
require_once plugin_dir_path( __DIR__ ) . 'includes/settings/class-general-settings-section.php';
$this->general_settings = new GeneralSettingsSection('footnotes_storage', 'footnotes-settings', 'General Settings');
}
/**
@ -1348,7 +1372,7 @@ class Settings {
* @since 1.5.0
*/
public function get_container( int $index ): string {
return $this->container[ $index ];
return $this->option_groups[ $index ];
}
/**
@ -1360,7 +1384,7 @@ class Settings {
* @since 1.5.6
*/
public function get_defaults( int $index ): array {
return $this->default[ $this->container[ $index ] ];
return $this->default[ $this->option_groups[ $index ] ];
}
/**
@ -1398,14 +1422,21 @@ class Settings {
* The Settings Container label will be the same as the Settings Container name.
*
* @since 1.5.0
* @todo Only register current tab?
*/
public function register_settings(): void {
// Register all settings.
$num_settings = count( $this->container );
for ( $i = 0; $i < $num_settings; $i++ ) {
register_setting( $this->get_container( $i ), $this->get_container( $i ) );
// Register all settings.
foreach ($this->default_settings as $option_groups_name => $option_groups_values) {
foreach ($option_groups_values as $setting_name => $setting_value) {
if (!is_array($setting_value)) {
register_setting( $option_groups_name, $setting_name );
} else {
register_setting( $option_groups_name, $setting_name, $setting_value['setting_args']);
}
}
}
}
/**
* Returns a singleton of this class.
*
@ -1421,46 +1452,46 @@ class Settings {
return self::$instance;
}
/**
* Loads all Settings from each Settings container.
* Loads all settings from each option group.
*
* @since 1.5.0
* @since 2.8.0 Renamed from `load_all()` to `load_options()`.
*/
private function load_all(): void {
private function load_options(): void {
// Clear current settings.
$this->settings = array();
$num_settings = count( $this->container );
for ( $i = 0; $i < $num_settings; $i++ ) {
// Load settings.
$this->settings = array_merge( $this->settings, $this->load( $i ) );
foreach ($this->option_groups as $option_group) {
$this->settings[$option_group] = $this->load_option( $option_group );
}
}
/**
* Loads all settings from specified Settings Containers.
* Loads all settings from a given option group.
*
* @param int $index Settings container index.
* @return (string|int)[] Loaded settings (or defaults if specified container is empty).
* @param string $option_group Option group slug.
* @return (string|int)[] Loaded settings (or defaults if specified option group is empty).
*
* @since 1.5.0
* @since 2.8.0 Renamed from `load()` to `load_option()`.
*/
private function load( int $index ): array {
// Load all settings from container.
$options = get_option( $this->get_container( $index ) );
// Load all default settings.
$default = $this->default[ $this->get_container( $index ) ];
private function load_option(string $option_group): array {
// Load all settings from option group.
$options = get_option( $option_group );
// No settings found, set them to their default value.
if ( empty( $options ) ) {
return $default;
return $this->default_settings[$option_group];
}
// Iterate through all available settings ( = default values).
foreach ( $default as $key => $value ) {
// Available setting not found in the container.
if ( ! array_key_exists( $key, $options ) ) {
foreach ( $this->default_settings[$option_group] as $setting_name => $setting_value ) {
// Available setting not found in the option group.
if ( ! array_key_exists( $setting_name, $options ) ) {
// Define the setting with its default value.
$options[ $key ] = $value;
$options[ $setting_name ] = $setting_value;
}
}
// Return settings loaded from Container.
// Return settings loaded from option group.
return $options;
}
}

View file

@ -0,0 +1,56 @@
<?php
/**
* File providing the `GeneralSettingsSection` class.
*
* @package footnotes
* @since 2.8.0
*/
declare(strict_types=1);
namespace footnotes\includes\settings;
require_once plugin_dir_path( __DIR__ ) . 'settings/class-settings-section.php';
use footnotes\includes\settings\general\ReferenceContainerSettingsGroup;
/**
* Class defining general plugin settings.
*
* @package footnotes
* @since 2.8.0
*/
class GeneralSettingsSection extends SettingsSection {
/**
* The groups of settings within this section.
*
* @var SettingsGroup[]
*
* @since 2.8.0
*/
protected array $settings_groups;
public function __construct(
$options_group_slug,
$section_slug,
$title
) {
$this->options_group_slug = $options_group_slug;
$this->section_slug = $section_slug;
$this->title = $title;
$this->load_dependencies();
$this->add_settings_groups(get_option( $this->options_group_slug ));
}
protected function load_dependencies(): void {
require_once plugin_dir_path( __DIR__ ) . 'settings/general/class-reference-container-settings-group.php';
}
protected function add_settings_groups(): void {
$this->settings_groups = array (
ReferenceContainerSettingsGroup::GROUP_ID => new ReferenceContainerSettingsGroup($this->options_group_slug, $this->section_slug),
);
}
}

View file

@ -0,0 +1,137 @@
<?php
/**
* File providing the `Setting` class.
*
* @package footnotes
* @since 2.8.0
*/
declare(strict_types=1);
namespace footnotes\includes\settings;
/**
* Class defining a configurable plugin setting.
*
* @package footnotes
* @since 2.8.0
*/
class Setting {
/**
* Setting value.
*
* @var mixed
*
* @since 2.8.0
*/
private $value;
public function __construct(
/**
* Setting group ID.
*
* @var string
*
* @since 2.8.0
*/
private string $group_id,
/**
* Setting section slug.
*
* @var string
*
* @since 2.8.0
*/
private string $options_group_slug,
/**
* Setting section slug.
*
* @var string
*
* @since 2.8.0
*/
private string $section_slug,
/**
* Setting slug.
*
* @var string
*
* @since 2.8.0
*/
public string $key,
/**
* Setting name.
*
* @var string
*
* @since 2.8.0
*/
public string $name,
/**
* Setting description.
*
* @var string|null
*
* @since 2.8.0
*/
public ?string $description,
/**
* Setting default value.
*
* @var mixed
*
* @since 2.8.0
*/
private $default_value,
/**
* Setting data type.
*
* @var string
*
* @since 2.8.0
*/
private string $type,
/**
* Setting input field type.
*
* @var string
*
* @since 2.8.0
*/
private string $input_type
) {
register_setting( $this->options_group_slug, $this->key, $this->get_setting_args());
}
public function get_setting_args(): array {
return array (
'type' => $this->type,
'description' => $this->description,
'default' => $this->default_value,
);
}
public function get_setting_field_args(): array {
return array (
'name' => $this->key,
'label_for' => $this->key,
'type' => $this->input_type,
'value' => $this->value,
'description' => $this->description,
);
}
public function get_options_group_slug(): string {
return $this->options_group_slug;
}
public function get_section_slug(): string {
return $this->section_slug;
}
}

View file

@ -0,0 +1,71 @@
<?php
/**
* File providing the `SettingsGroup` class.
*
* @package footnotes
* @since 2.8.0
*/
declare(strict_types=1);
namespace footnotes\includes\settings;
use footnotes\admin\layout as Layout;
/**
* Class defining a group of plugin settings within a section.
*
* @package footnotes
* @since 2.8.0
*/
abstract class SettingsGroup {
/**
* Setting section slug.
*
* @var string
*
* @since 2.8.0
*/
protected string $options_group_slug;
/**
* Setting section slug.
*
* @var string
*
* @since 2.8.0
*/
protected string $section_slug;
/**
* Setting group ID.
*
* @var string
*
* @since 2.8.0
*/
const GROUP_ID = '';
/**
* The setting classes.
*
* @var string[]
*
* @since 2.8.0
*/
protected array $setting_classes;
/**
* The general settings.
*
* @var Setting[]
*
* @since 2.8.0
*/
protected array $settings;
protected abstract function load_dependencies(): void;
protected abstract function add_settings(array $options): void;
protected abstract function add_settings_fields(Layout\Settings $component): void;
}

View file

@ -0,0 +1,96 @@
<?php
/**
* File providing the (new) `SettingsSection` class.
*
* @package footnotes
* @since 2.8.0
*/
declare(strict_types=1);
namespace footnotes\includes\settings;
use footnotes\admin\layout as Layout;
/**
* Class defining plugin settings.
*
* @package footnotes
* @since 2.8.0
*/
abstract class SettingsSection {
/**
* Setting options group slug.
*
* @var string
*
* @since 2.8.0
*/
protected string $options_group_slug;
/**
* Settings section slug.
*
* @var string
*
* @since 2.8.0
*/
protected string $section_slug = '';
/**
* Settings section title.
*
* @var string
*
* @since 2.8.0
*/
protected string $title = '';
/**
* The groups of settings within this section.
*
* @var SettingGroup[]
*
* @since 2.8.0
*/
protected array $settings_groups;
protected abstract function load_dependencies(): void;
public function add_settings_section(): void {
add_settings_section(
$this->section_slug,
$this->title,
array($this, 'setting_section_callback'),
'footnotes'
);
}
public function add_settings_fields($component): void {
foreach($this->settings_groups as $settings_group) {
$settings_group->add_settings_fields($component);
}
}
public function setting_section_callback(): void {
echo "<hr>";
}
protected abstract function add_settings_groups(): void;
public function get_options_group_slug(): string {
return $this->options_group_slug;
}
public function get_section_slug(): string {
return $this->section_slug;
}
public function get_title(): string {
return $this->title;
}
public function get_settings_group(string $group_id) {
return $this->settings_groups[$group_id];
}
}

View file

@ -0,0 +1,122 @@
<?php
/**
* File providing the `ReferenceContainerSettingsGroup` class.
*
* @package footnotes
* @since 2.8.0
*/
declare(strict_types=1);
namespace footnotes\includes\settings\general;
require_once plugin_dir_path( __DIR__ ) . 'class-settings-group.php';
use footnotes\includes\settings\Setting;
use footnotes\includes\settings\SettingsGroup;
use footnotes\admin\layout\Settings as SettingsLayout;
/**
* Class defining the reference container settings.
*
* @package footnotes
* @since 2.8.0
*/
class ReferenceContainerSettingsGroup extends SettingsGroup {
/**
* Setting group ID.
*
* @var string
*
* @since 2.8.0
*/
const GROUP_ID = 'reference-container';
/**
* Settings container key for the label of the reference container.
*
* @var string
*
* @since 1.5.0
*/
const REFERENCE_CONTAINER_NAME = array(
'key' => 'footnote_inputfield_references_label',
'name' => 'Reference Container Name',
'description' => 'The title of the reference container.',
'default_value' => 'Reference',
'type' => 'string',
'input_type' => 'text'
);
/**
* The general settings.
*
* @var Setting[]
*
* @since 2.8.0
*/
protected array $settings;
public function __construct(
/**
* Setting options group slug.
*
* @var string
*
* @since 2.8.0
*/
protected string $options_group_slug,
/**
* Setting section slug.
*
* @var string
*
* @since 2.8.0
*/
protected string $section_slug
) {
$this->load_dependencies();
$this->add_settings(get_option( $this->options_group_slug ));
}
protected function load_dependencies(): void {
require_once plugin_dir_path( __DIR__ ) . 'class-setting.php';
}
protected function add_settings(array $options): void {
$this->settings = array(
self::REFERENCE_CONTAINER_NAME['key'] => $this->add_setting(self::REFERENCE_CONTAINER_NAME)
);
}
private function add_setting(array $setting): Setting {
extract( $setting );
return new Setting(
self::GROUP_ID,
$this->options_group_slug,
$this->section_slug,
$key,
$name,
$description,
$default_value,
$type,
$input_type
);
}
public function add_settings_fields($component): void {
foreach ($this->settings as $setting) {
add_settings_field(
$setting->key,
__( $setting->name, 'footnotes' ),
array ($component, 'setting_field_callback'),
'footnotes',
$setting->get_section_slug(),
$setting->get_setting_field_args()
);
}
}
}

View file

@ -0,0 +1,106 @@
<?php
/**
* File providing the `ReferenceContainerNameSetting` class.
*
* @package footnotes
* @since 2.8.0
*/
declare(strict_types=1);
namespace footnotes\includes\settings\general\ReferenceContainer;
require_once plugin_dir_path( dirname( __FILE__, 2 ) ) . 'class-setting.php';
use footnotes\includes\settings as Settings;
/**
* Class defining the reference container name setting.
*
* @package footnotes
* @since 2.8.0
*/
class ReferenceContainerNameSetting extends Settings\Setting {
/**
* Setting slug.
*
* @var string
*
* @since 2.8.0
*/
const KEY = 'footnote_inputfield_references_label';
/**
* Setting name.
*
* @var string
*
* @since 2.8.0
*/
const NAME = 'Reference Container Title';
/**
* Setting description.
*
* @var string
*
* @since 2.8.0
*/
const DESCRIPTION = 'The title of the reference container.';
/**
* Setting default value.
*
* @var mixed
*
* @since 2.8.0
*/
const DEFAULT_VALUE = 'Reference';
/**
* Setting data type.
*
* @var string
*
* @since 2.8.0
*/
const TYPE = 'string';
/**
* Setting input field type.
*
* @var string
*
* @since 2.8.0
*/
const INPUT_TYPE = 'text';
public function __construct(
/**
* Setting group ID.
*
* @var string
*
* @since 2.8.0
*/
private string $section_group_id,
/**
* Setting section slug.
*
* @var string
*
* @since 2.8.0
*/
private string $options_group_slug,
/**
* Setting section slug.
*
* @var string
*
* @since 2.8.0
*/
private string $section_slug
) {
register_setting( $this->options_group_slug, self::NAME, $this->get_setting_args());
}
}