From f9f11e2540266f216fd97a6e8575ea1b37325ed7 Mon Sep 17 00:00:00 2001 From: Tang Rufus Date: Sat, 25 Mar 2017 13:34:12 +0800 Subject: [PATCH] Use both PSR-2 and WordPress coding standard --- .stickler.yml | 5 +- .styleci.yml | 1 + Gruntfile.js | 136 +++++----- class-plugin.php | 329 +++++++++++++------------ composer.json | 186 +++++++------- composer.lock | 14 +- package.json | 64 ++--- partials/last-name-field.php | 4 +- partials/section-description.php | 6 +- ruleset.xml | 87 ++++++- src/Config.php | 127 +++++----- src/FieldConfig.php | 30 +-- src/FunctionInvokerTrait.php | 123 ++++----- src/MenuPageConfig.php | 88 +++---- src/MenuPages.php | 131 +++++----- src/OptionStore.php | 48 ++-- src/OptionStoreInterface.php | 29 +-- src/Sanitizer.php | 88 ++++--- src/SectionConfig.php | 96 ++++---- src/SettingConfig.php | 255 +++++++++---------- src/Settings.php | 198 +++++++-------- src/View.php | 213 ++++++++-------- src/ViewEchoTrait.php | 36 +-- src/ViewFactory.php | 88 +++---- src/ViewInterface.php | 23 +- src/partials/basic-options-page.php | 8 +- src/partials/checkbox-field.php | 8 +- src/partials/common-attributes.php | 16 +- src/partials/description-paragraph.php | 10 +- src/partials/input-field.php | 4 +- src/partials/options-form.php | 16 +- src/partials/section-description.php | 4 +- src/partials/tabbed-options-page.php | 37 ++- src/partials/textarea-field.php | 6 +- tests/_bootstrap.php | 2 +- tests/_support/AcceptanceTester.php | 22 +- tests/_support/Helper/Acceptance.php | 8 +- tests/_support/Helper/Unit.php | 8 +- tests/_support/UnitTester.php | 21 +- tests/acceptance/CheckboxFieldCept.php | 8 +- tests/acceptance/InputFieldCept.php | 16 +- tests/acceptance/MenuPageLinkCept.php | 2 +- tests/acceptance/TextareaFieldCept.php | 4 +- tests/acceptance/_bootstrap.php | 2 +- tests/ruleset.xml | 18 -- tests/unit/ConfigTest.php | 87 ++++--- tests/unit/FieldConfigTest.php | 15 +- tests/unit/MenuPageConfigTest.php | 62 ++--- tests/unit/MenuPagesTest.php | 9 +- tests/unit/OptionStoreTest.php | 21 +- tests/unit/SanitizerTest.php | 101 ++++---- tests/unit/SectionConfigTest.php | 36 +-- tests/unit/SettingConfigTest.php | 184 ++++++++------ tests/unit/ViewEchoTraitTest.php | 33 +-- tests/unit/ViewFactoryTest.php | 17 +- tests/unit/ViewTest.php | 7 +- tests/unit/_bootstrap.php | 2 +- wp-better-settings.php | 17 +- 58 files changed, 1696 insertions(+), 1520 deletions(-) create mode 100644 .styleci.yml delete mode 100644 tests/ruleset.xml diff --git a/.stickler.yml b/.stickler.yml index 92a5051..45a9dcc 100644 --- a/.stickler.yml +++ b/.stickler.yml @@ -1,6 +1,3 @@ linters: phpcs: - standard: 'WordPress' - -files: - ignore: ['assets/*', 'tests/*', 'vendor/*'] + standard: './ruleset.xml' diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000..247a09c --- /dev/null +++ b/.styleci.yml @@ -0,0 +1 @@ +preset: psr2 diff --git a/Gruntfile.js b/Gruntfile.js index 28b3ca6..c3f05d8 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -11,83 +11,83 @@ * @see https://github.com/TypistTech/wp-better-settings */ -module.exports = function ( grunt ) { +module.exports = function (grunt) { - 'use strict'; + 'use strict'; - // Project configuration. - grunt.initConfig( { + // Project configuration. + grunt.initConfig({ - pkg: grunt.file.readJSON( 'package.json' ), + pkg: grunt.file.readJSON('package.json'), - // Bump version numbers. - version: { - composer: { - options: { - prefix: '"version"\\:\\s+"' - }, - src: ['composer.json'] - }, - changelog: { - options: { - prefix: 'future-release=' - }, - src: ['.github_changelog_generator'] - }, - php: { - options: { - prefix: '\\* Version:\\s+' - }, - src: ['<%= pkg.name %>.php'] - } - }, + // Bump version numbers. + version: { + composer: { + options: { + prefix: '"version"\\:\\s+"' + }, + src: ['composer.json'] + }, + changelog: { + options: { + prefix: 'future-release=' + }, + src: ['.github_changelog_generator'] + }, + php: { + options: { + prefix: '\\* Version:\\s+' + }, + src: ['<%= pkg.name %>.php'] + } + }, - // Clean the build folder. - clean: { - "pre-build": { - src: [ - 'build/', - 'release/', - 'vendor/' - ] - } - }, + // Clean the build folder. + clean: { + "pre-build": { + src: [ + 'build/', + 'release/', + 'vendor/' + ] + } + }, - // Copy to build folder. - copy: { - build: { - expand: true, - src: [ - 'partials/**', - 'src/**', - 'vendor/**', - 'class-plugin.php', - 'LICENSE', - '<%= pkg.name %>.php' - ], - dest: 'build/' - } - }, + // Copy to build folder. + copy: { + build: { + expand: true, + src: [ + 'partials/**', + 'src/**', + 'vendor/**', + 'class-plugin.php', + 'LICENSE', + '<%= pkg.name %>.php' + ], + dest: 'build/' + } + }, - compress: { - build: { - options: { - archive: 'release/<%= pkg.name %>.zip' - }, - expand: true, - dest: '<%= pkg.name %>/', - cwd: 'build/', - src: ['**'] - } - } + compress: { + build: { + options: { + archive: 'release/<%= pkg.name %>.zip' + }, + expand: true, + dest: '<%= pkg.name %>/', + cwd: 'build/', + src: ['**'] + } + } - } ); + }); - require( 'load-grunt-tasks' )( grunt ); - grunt.registerTask( 'pre-build', ['clean:pre-build'] ); - grunt.registerTask( 'build', ['copy:build', 'compress:build'] ); - grunt.registerTask( 'pre-tag', ['version'] ); + require('load-grunt-tasks')(grunt); + grunt.registerTask('pre-build', ['clean:pre-build']); + grunt.registerTask('build', ['copy:build', 'compress:build']); + grunt.registerTask('pre-tag', ['version']); - grunt.util.linefeed = '\n'; + grunt.util.linefeed = '\n'; }; diff --git a/class-plugin.php b/class-plugin.php index ee66d49..923e95a 100644 --- a/class-plugin.php +++ b/class-plugin.php @@ -12,7 +12,7 @@ * @see https://github.com/TypistTech/wp-better-settings */ -namespace WP_Better_Settings; +namespace TypistTech\WPBetterSettings; /** * Class Plugin. @@ -21,171 +21,176 @@ * * @since 0.1.0 */ -class Plugin { - /** - * Options store instance. - * - * @since 0.1.0 - * - * @var Option_Store_Interface - */ - protected $options_store; +class Plugin +{ + /** + * Options store instance. + * + * @since 0.1.0 + * + * @var OptionStoreInterface + */ + protected $optionStore; - /** - * Launch the initialization process. - * - * @since 0.1.0 - */ - public function init() { - $this->options_store = new Option_Store; - $this->init_settings_page(); - } + /** + * Launch the initialization process. + * + * @since 0.1.0 + */ + public function init() + { + $this->optionStore = new OptionStore; + $this->initSettingsPage(); + } - /** - * Initialize Settings page. - * - * @since 0.1.0 - */ - public function init_settings_page() { - $menu_pages = new Menu_Pages( $this->page_configs() ); - $settings = new Settings( $this->settings_configs(), $this->options_store ); + /** + * Initialize Settings page. + * + * @since 0.1.0 + */ + public function initSettingsPage() + { + $menuPages = new MenuPages($this->pageConfigs()); + $settings = new Settings($this->settingsConfigs(), $this->optionStore); - // Register the settings page with WordPress. - add_action( 'admin_menu', [ $menu_pages, 'admin_menu' ] ); - add_action( 'admin_init', [ $settings, 'admin_init' ] ); - } + // Register the settings page with WordPress. + add_action('admin_menu', [ $menuPages, 'adminMenu' ]); + add_action('admin_init', [ $settings, 'adminInit' ]); + } - /** - * Page configs - * - * #since 0.3.0 - * - * @return Menu_Page_Config[] - */ - private function page_configs() : array { - return [ - new Menu_Page_Config( [ - 'menu_slug' => 'wpbs_1', - 'page_title' => 'WP Better Settings', - 'menu_title' => 'WP Better Settings', - 'option_group' => 'wpbs_1', - ] ), - new Menu_Page_Config( [ - 'menu_slug' => 'wpbs_2', - 'page_title' => 'WP Better Settings Two', - 'menu_title' => 'WPBS Two', - 'option_group' => 'wpbs_2', - 'parent_slug' => 'wpbs_1', - 'view' => View_Factory::build( 'basic-options-page' ), - ] ), - ]; - } + /** + * Page configs + * + * #since 0.3.0 + * + * @return MenuPageConfig[] + */ + private function pageConfigs() : array + { + return [ + new MenuPageConfig([ + 'menu_slug' => 'wpbs_1', + 'page_title' => 'WP Better Settings', + 'menu_title' => 'WP Better Settings', + 'option_group' => 'wpbs_1', + ]), + new MenuPageConfig([ + 'menu_slug' => 'wpbs_2', + 'page_title' => 'WP Better Settings Two', + 'menu_title' => 'WPBS Two', + 'option_group' => 'wpbs_2', + 'parent_slug' => 'wpbs_1', + 'view' => ViewFactory::build('basic-options-page'), + ]), + ]; + } - /** - * Setting configs - * - * @since 0.3.0 - * - * @return Setting_Config[] - */ - private function settings_configs() : array { - return [ - new Setting_Config( [ - 'option_group' => 'wpbs_1', - 'option_name' => 'wpbs_option_1', - 'sections' => [ - new Section_Config( [ - 'id' => 'wpbs_section_1', - 'page' => 'wpbs_1', - 'title' => __( 'My Useless Name Settings', 'as-settings-better-v1' ), - 'desc' => 'Just my section desc', - 'fields' => [ - new Field_Config( [ - 'id' => 'my_name', - 'title' => __( 'My Name', 'as-settings-better-v1' ), - 'default' => 'Tang Rufus', - 'view' => View_Factory::build( 'text-field' ), - 'desc' => 'I am a description paragraph', - ] ), - new Field_Config( [ - 'id' => 'my_email', - 'title' => __( 'My Email', 'as-settings-better-v1' ), - 'view' => View_Factory::build( 'email-field' ), - 'sanitize_callback' => [ Sanitizer::class, 'sanitize_email' ], - ] ), - new Field_Config( [ - 'id' => 'my_url', - 'title' => __( 'My Url', 'as-settings-better-v1' ), - 'default' => 'https://www.typist.tech', - 'view' => View_Factory::build( 'url-field' ), - 'sanitize_callback' => 'esc_url_raw', - ] ), - new Field_Config( [ - 'id' => 'my_textarea', - 'title' => __( 'My Textarea', 'wp-better-settings' ), - 'view' => View_Factory::build( 'textarea-field' ), - 'rows' => 11, - ] ), - new Field_Config( [ - 'id' => 'my_checkbox', - 'title' => __( 'My Checkbox', 'wp-better-settings' ), - 'view' => View_Factory::build( 'checkbox-field' ), - 'label' => __( 'Click me', 'wp-cloudflare-guard' ), - 'desc' => __( 'Checkmate', 'wp-cloudflare-guard' ), - 'sanitize_callback' => [ Sanitizer::class, 'sanitize_checkbox' ], - ] ), - new Field_Config( [ - 'id' => 'my_disabled_input', - 'title' => __( 'My Disabled Input', 'as-settings-better-v1' ), - 'desc' => 'Disabled on purpose', - 'view' => View_Factory::build( 'text-field' ), - 'disabled' => true, - ] ), - new Field_Config( [ - 'id' => 'my_disabled_textarea', - 'title' => __( 'My Disabled Textarea', 'wp-better-settings' ), - 'view' => View_Factory::build( 'textarea-field' ), - 'desc' => 'You shall not type', - 'disabled' => true, - ] ), - new Field_Config( [ - 'id' => 'my_disabled_checkbox', - 'title' => __( 'My Disabled Checkbox', 'wp-better-settings' ), - 'view' => View_Factory::build( 'checkbox-field' ), - 'desc' => __( 'You shall not check', 'wp-cloudflare-guard' ), - 'disabled' => true, - 'sanitize_callback' => [ Sanitizer::class, 'sanitize_checkbox' ], - ] ), - ], - ] ), - ], - ] ), + /** + * Setting configs + * + * @since 0.3.0 + * + * @return SettingConfig[] + */ + private function settingsConfigs() : array + { + return [ + new SettingConfig([ + 'option_group' => 'wpbs_1', + 'option_name' => 'wpbs_option_1', + 'sections' => [ + new SectionConfig([ + 'id' => 'wpbs_section_1', + 'page' => 'wpbs_1', + 'title' => __('My Useless Name Settings', 'wp-better-settings'), + 'desc' => 'Just my section desc', + 'fields' => [ + new FieldConfig([ + 'id' => 'my_name', + 'title' => __('My Name', 'wp-better-settings'), + 'default' => 'Tang Rufus', + 'view' => ViewFactory::build('text-field'), + 'desc' => 'I am a description paragraph', + ]), + new FieldConfig([ + 'id' => 'my_email', + 'title' => __('My Email', 'wp-better-settings'), + 'view' => ViewFactory::build('email-field'), + 'sanitize_callback' => [ Sanitizer::class, 'sanitize_email' ], + ]), + new FieldConfig([ + 'id' => 'my_url', + 'title' => __('My Url', 'wp-better-settings'), + 'default' => 'https://www.typist.tech', + 'view' => ViewFactory::build('url-field'), + 'sanitize_callback' => 'esc_url_raw', + ]), + new FieldConfig([ + 'id' => 'my_textarea', + 'title' => __('My Textarea', 'wp-better-settings'), + 'view' => ViewFactory::build('textarea-field'), + 'rows' => 11, + ]), + new FieldConfig([ + 'id' => 'my_checkbox', + 'title' => __('My Checkbox', 'wp-better-settings'), + 'view' => ViewFactory::build('checkbox-field'), + 'label' => __('Click me', 'wp-better-settings'), + 'desc' => __('Checkmate', 'wp-better-settings'), + 'sanitize_callback' => [ Sanitizer::class, 'sanitize_checkbox' ], + ]), + new FieldConfig([ + 'id' => 'my_disabled_input', + 'title' => __('My Disabled Input', 'wp-better-settings'), + 'desc' => 'Disabled on purpose', + 'view' => ViewFactory::build('text-field'), + 'disabled' => true, + ]), + new FieldConfig([ + 'id' => 'my_disabled_textarea', + 'title' => __('My Disabled Textarea', 'wp-better-settings'), + 'view' => ViewFactory::build('textarea-field'), + 'desc' => 'You shall not type', + 'disabled' => true, + ]), + new FieldConfig([ + 'id' => 'my_disabled_checkbox', + 'title' => __('My Disabled Checkbox', 'wp-better-settings'), + 'view' => ViewFactory::build('checkbox-field'), + 'desc' => __('You shall not check', 'wp-better-settings'), + 'disabled' => true, + 'sanitize_callback' => [ Sanitizer::class, 'sanitize_checkbox' ], + ]), + ], + ]), + ], + ]), - new Setting_Config( [ - 'option_group' => 'wpbs_2', - 'option_name' => 'wpbs_option_2', - 'sections' => [ - new Section_Config( [ - 'id' => 'wpbs_section_2', - 'title' => __( 'Useless Name Settings', 'as-settings-better-v1' ), - 'page' => 'wpbs_2', - 'view' => plugin_dir_path( __FILE__ ) . 'partials/section-description.php', - 'fields' => [ - new Field_Config( [ - 'id' => 'wpbs_first_name', - 'title' => __( 'First Name', 'as-settings-better-v1' ), - 'view' => View_Factory::build( 'text-field' ), - 'default' => 'Elliot', - ] ), - new Field_Config( [ - 'id' => 'wpbs_last_name', - 'title' => __( 'Last Name', 'as-settings-better-v1' ), - 'view' => plugin_dir_path( __FILE__ ) . 'partials/last-name-field.php', - ] ), - ], - ] ), - ], - ] ), - ]; - } + new SettingConfig([ + 'option_group' => 'wpbs_2', + 'option_name' => 'wpbs_option_2', + 'sections' => [ + new SectionConfig([ + 'id' => 'wpbs_section_2', + 'title' => __('Useless Name Settings', 'wp-better-settings'), + 'page' => 'wpbs_2', + 'view' => plugin_dir_path(__FILE__) . 'partials/section-description.php', + 'fields' => [ + new FieldConfig([ + 'id' => 'wpbs_first_name', + 'title' => __('First Name', 'wp-better-settings'), + 'view' => ViewFactory::build('text-field'), + 'default' => 'Elliot', + ]), + new FieldConfig([ + 'id' => 'wpbs_last_name', + 'title' => __('Last Name', 'wp-better-settings'), + 'view' => plugin_dir_path(__FILE__) . 'partials/last-name-field.php', + ]), + ], + ]), + ], + ]), + ]; + } } diff --git a/composer.json b/composer.json index 35925c5..22738af 100644 --- a/composer.json +++ b/composer.json @@ -1,96 +1,94 @@ { - "name": "typisttech/wp-better-settings", - "description": "A simplified OOP implementation of the WP Settings API", - "keywords": [ - "wordpress", - "wp", - "settings api" - ], - "homepage": "https://www.typist.tech/projects/wp-better-settings", - "license": "GPL-2.0+", - "authors": [ - { - "name": "Typist Tech", - "email": "wp-better-settings@typist.tech", - "homepage": "https://www.typist.tech/" - }, - { - "name": "Tang Rufus", - "email": "tangrufus@gmail.com", - "homepage": "https://www.typist.tech/", - "role": "Developer" - } - ], - "support": { - "email": "wp-better-settings@typist.tech", - "issues": "https://github.com/TypistTech/wp-better-settings/issues", - "source": "https://github.com/TypistTech/wp-better-settings" - }, - "require": { - "php": ">7.0" - }, - "require-dev": { - "codeception/mockery-module": "^0.2.2", - "jakoch/phantomjs-installer": "^2.1", - "lucatume/wp-browser": "^1.19", - "neronmoon/scriptsdev": "^0.1.1", - "php-mock/php-mock-phpunit": "^1.1", - "site5/phantoman": "^1.1", - "wp-coding-standards/wpcs": "^0.10.0" - }, - "autoload": { - "psr-4": { - "TypistTech\\WPBetterSettings\\": "src/" - } - }, - "scripts": { - "build": [ - "npm update", - "grunt pre-build", - "composer install --no-dev --prefer-dist --no-suggest", - "grunt build" - ], - "check-style": [ - "phpcs --standard=ruleset.xml --colors -p -s .", - "phpcs --standard=tests/ruleset.xml --colors -p -s tests" - ], - "fix-style": [ - "phpcbf --standard=ruleset.xml -p --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 .", - "phpcbf --standard=tests/ruleset.xml -p --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 tests" - ], - "install-dev-extra": [ - "PhantomInstaller\\Installer::installPhantomJS", - "phpcs --config-set installed_paths vendor/wp-coding-standards/wpcs" - ], - "pre-tag": [ - "npm update", - "grunt pre-tag", - "doctoc README.md", - "github_changelog_generator --no-verbose" - ], - "test": [ - "@test-unit", - "@test-acceptance" - ], - "test-acceptance": "codecept run acceptance", - "test-unit": "codecept run unit", - "test-with-coverage": [ - "codecept run unit --coverage --coverage-xml --coverage-html", - "@test-acceptance" - ] - }, - "extra": { - "scripts-dev": { - "post-install-cmd": [ - "@install-dev-extra" - ], - "post-update-cmd": [ - "@install-dev-extra" - ] - } - }, - "config": { - "optimize-autoloader": true, - "sort-packages": true - } + "name": "typisttech/wp-better-settings", + "description": "A simplified OOP implementation of the WP Settings API", + "keywords": [ + "wordpress", + "wp", + "settings api" + ], + "homepage": "https://www.typist.tech/projects/wp-better-settings", + "license": "GPL-2.0+", + "authors": [ + { + "name": "Typist Tech", + "email": "wp-better-settings@typist.tech", + "homepage": "https://www.typist.tech/" + }, + { + "name": "Tang Rufus", + "email": "tangrufus@gmail.com", + "homepage": "https://www.typist.tech/", + "role": "Developer" + } + ], + "support": { + "email": "wp-better-settings@typist.tech", + "issues": "https://github.com/TypistTech/wp-better-settings/issues", + "source": "https://github.com/TypistTech/wp-better-settings" + }, + "require": { + "php": ">7.0" + }, + "require-dev": { + "codeception/mockery-module": "^0.2.2", + "jakoch/phantomjs-installer": "^2.1", + "lucatume/wp-browser": "^1.19", + "neronmoon/scriptsdev": "^0.1.1", + "php-mock/php-mock-phpunit": "^1.1", + "site5/phantoman": "^1.1", + "wp-coding-standards/wpcs": "^0.11.0" + }, + "autoload": { + "psr-4": { + "TypistTech\\WPBetterSettings\\": "src/" + } + }, + "scripts": { + "build": [ + "npm update", + "grunt pre-build", + "composer install --no-dev --prefer-dist --no-suggest", + "grunt build" + ], + "check-style": [ + "phpcs --standard=ruleset.xml --colors -p -s ." + ], + "fix-style": [ + "phpcbf --standard=ruleset.xml -p --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 ." + ], + "install-dev-extra": [ + "PhantomInstaller\\Installer::installPhantomJS", + "phpcs --config-set installed_paths vendor/wp-coding-standards/wpcs" + ], + "pre-tag": [ + "npm update", + "grunt pre-tag", + "doctoc README.md", + "github_changelog_generator --no-verbose" + ], + "test": [ + "@test-unit", + "@test-acceptance" + ], + "test-acceptance": "codecept run acceptance", + "test-unit": "codecept run unit", + "test-with-coverage": [ + "codecept run unit --coverage --coverage-xml --coverage-html", + "@test-acceptance" + ] + }, + "extra": { + "scripts-dev": { + "post-install-cmd": [ + "@install-dev-extra" + ], + "post-update-cmd": [ + "@install-dev-extra" + ] + } + }, + "config": { + "optimize-autoloader": true, + "sort-packages": true + } } diff --git a/composer.lock b/composer.lock index 6347df5..221ce14 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "82d65c1d1d3c174d20acb3159929adef", + "content-hash": "009d0c04690ee061624cbbc6ddd71afb", "packages": [], "packages-dev": [ { @@ -4471,20 +4471,20 @@ }, { "name": "wp-coding-standards/wpcs", - "version": "0.10.0", + "version": "0.11.0", "source": { "type": "git", "url": "https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards.git", - "reference": "b39490465f6fd7375743a395019cd597e12119c9" + "reference": "407e4b85f547a5251185f89ceae6599917343388" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WordPress-Coding-Standards/WordPress-Coding-Standards/zipball/b39490465f6fd7375743a395019cd597e12119c9", - "reference": "b39490465f6fd7375743a395019cd597e12119c9", + "url": "https://api.github.com/repos/WordPress-Coding-Standards/WordPress-Coding-Standards/zipball/407e4b85f547a5251185f89ceae6599917343388", + "reference": "407e4b85f547a5251185f89ceae6599917343388", "shasum": "" }, "require": { - "squizlabs/php_codesniffer": "^2.6" + "squizlabs/php_codesniffer": "^2.8.1" }, "type": "library", "notification-url": "https://packagist.org/downloads/", @@ -4503,7 +4503,7 @@ "standards", "wordpress" ], - "time": "2016-08-29T20:04:47+00:00" + "time": "2017-03-20T23:17:58+00:00" }, { "name": "xamin/handlebars.php", diff --git a/package.json b/package.json index bebede6..24c6b0d 100644 --- a/package.json +++ b/package.json @@ -1,34 +1,34 @@ { - "name": "wp-better-settings", - "version": "0.8.1", - "description": "A simplified OOP implementation of the WP Settings API", - "keywords": [ - "wordpress", - "wp", - "settings api" - ], - "homepage": "https://github.com/TypistTech/wp-better-settings", - "bugs": { - "email": "wp-better-settings@typist.tech", - "url": "https://github.com/TypistTech/wp-better-settings/issues" - }, - "license": "GPL-2.0+", - "author": "Typist Tech (http://typist.tech/)", - "contributors": [ - "Tang Rufus (http://typist.tech/)" - ], - "repository": { - "type": "git", - "url": "https://github.com/TypistTech/wp-better-settings.git" - }, - "main": "Gruntfile.js", - "devDependencies": { - "grunt": "^1.0.1", - "grunt-contrib-clean": "^1.0.0", - "grunt-contrib-compress": "^1.4.1", - "grunt-contrib-copy": "^1.0.0", - "grunt-version": "^1.1.1", - "load-grunt-tasks": "^3.5.2" - }, - "private": true + "name": "wp-better-settings", + "version": "0.8.1", + "description": "A simplified OOP implementation of the WP Settings API", + "keywords": [ + "wordpress", + "wp", + "settings api" + ], + "homepage": "https://github.com/TypistTech/wp-better-settings", + "bugs": { + "email": "wp-better-settings@typist.tech", + "url": "https://github.com/TypistTech/wp-better-settings/issues" + }, + "license": "GPL-2.0+", + "author": "Typist Tech (http://typist.tech/)", + "contributors": [ + "Tang Rufus (http://typist.tech/)" + ], + "repository": { + "type": "git", + "url": "https://github.com/TypistTech/wp-better-settings.git" + }, + "main": "Gruntfile.js", + "devDependencies": { + "grunt": "^1.0.1", + "grunt-contrib-clean": "^1.0.0", + "grunt-contrib-compress": "^1.4.1", + "grunt-contrib-copy": "^1.0.0", + "grunt-version": "^1.1.1", + "load-grunt-tasks": "^3.5.2" + }, + "private": true } diff --git a/partials/last-name-field.php b/partials/last-name-field.php index a334a8e..8fff6ba 100644 --- a/partials/last-name-field.php +++ b/partials/last-name-field.php @@ -12,10 +12,10 @@ * @see https://github.com/TypistTech/wp-better-settings */ -namespace WP_Better_Settings; +namespace TypistTech\WPBetterSettings; /* @var \ArrayObject $context Context passed through from Settings class. */ echo ''; +echo 'value="' . esc_html($context->value) . '">'; diff --git a/partials/section-description.php b/partials/section-description.php index 712a5fe..8eaf6ea 100644 --- a/partials/section-description.php +++ b/partials/section-description.php @@ -12,9 +12,9 @@ * @see https://github.com/TypistTech/wp-better-settings */ -namespace WP_Better_Settings; +namespace TypistTech\WPBetterSettings; esc_html_e( - 'These settings store a completely useless pair of first and last names.', - 'wp-better-settings' + 'These settings store a completely useless pair of first and last names.', + 'wp-better-settings' ); diff --git a/ruleset.xml b/ruleset.xml index 58be007..ea79adf 100644 --- a/ruleset.xml +++ b/ruleset.xml @@ -12,20 +12,91 @@ ~ @see https://github.com/TypistTech/wp-better-settings --> - + - Generally-applicable sniffs for WordPress plugins + PSR 2 and WordPress Coding Standards for Plugins - ./ - - /Gruntfile.js - /.idea/* /build/* /node_modules/* /release/* - /tests/* + /tests/_data/* + /tests/_output/* /vendor/* + /Gruntfile.js + + + + + /*.php + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + */_bootstrap.php + + + + */_bootstrap.php + + + + /tests/* + + + + /tests/* + + + + /tests/* + - + + /tests/* + diff --git a/src/Config.php b/src/Config.php index 205bad2..a16b5f3 100644 --- a/src/Config.php +++ b/src/Config.php @@ -23,69 +23,76 @@ * * @since 0.1.0 */ -class Config extends ArrayObject { - /** - * Config constructor. - * - * @since 0.1.0 - * - * @param array $config Custom config array. - */ - public function __construct( array $config = [] ) { - $config = array_replace_recursive( $this->default_config(), $config ); +class Config extends ArrayObject +{ + /** + * Config constructor. + * + * @since 0.1.0 + * + * @param array $config Custom config array. + */ + public function __construct(array $config = []) + { + $config = array_replace_recursive($this->defaultConfig(), $config); - // Make sure the config entries can be accessed as properties. - parent::__construct( - array_filter( $config ), ArrayObject::ARRAY_AS_PROPS - ); - } + // Make sure the config entries can be accessed as properties. + parent::__construct( + array_filter($config), + ArrayObject::ARRAY_AS_PROPS + ); + } - /** - * Default config. - * - * To be overridden by subclass. - * - * @since 0.1.0 - * @return array - */ - protected function default_config() : array { - return []; - } + /** + * Default config. + * + * To be overridden by subclass. + * + * @since 0.1.0 + * @return array + */ + protected function defaultConfig() : array + { + return []; + } - /** - * Check whether the Config has a specific key. - * - * @since 0.1.0 - * - * @param string $key The key to check the existence for. - * - * @return bool Whether the specified key exists. - */ - public function has_key( string $key ) : bool { - return array_key_exists( $key, (array) $this ); - } + /** + * Get the value of a specific key. + * + * @since 0.1.0 + * + * @param string $key The key to get the value for. + * + * @return mixed Value of the requested key. + * Or, null if undefined. + */ + public function getKey(string $key) + { + return $this[ $key ] ?? null; + } - /** - * Get the value of a specific key. - * - * @since 0.1.0 - * - * @param string $key The key to get the value for. - * - * @return mixed Value of the requested key. - * Or, null if undefined. - */ - public function get_key( string $key ) { - return $this[ $key ] ?? null; - } + /** + * Get an array with all the keys. + * + * @since 0.1.0 + * @return array Array of config keys. + */ + public function getKeys() : array + { + return array_keys((array) $this); + } - /** - * Get an array with all the keys. - * - * @since 0.1.0 - * @return array Array of config keys. - */ - public function get_keys() : array { - return array_keys( (array) $this ); - } + /** + * Check whether the Config has a specific key. + * + * @since 0.1.0 + * + * @param string $key The key to check the existence for. + * + * @return bool Whether the specified key exists. + */ + public function hasKey(string $key) : bool + { + return array_key_exists($key, (array) $this); + } } diff --git a/src/FieldConfig.php b/src/FieldConfig.php index 646e943..56f1a5b 100644 --- a/src/FieldConfig.php +++ b/src/FieldConfig.php @@ -32,19 +32,21 @@ * * @since 0.1.0 */ -class FieldConfig extends Config { - use ViewEchoTrait; +class FieldConfig extends Config +{ + use ViewEchoTrait; - /** - * Default config of Field_Config. - * - * @since 0.1.0 - * @return array - */ - protected function default_config() : array { - return [ - 'callback' => [ $this, 'echo_view' ], - 'sanitize_callback' => 'sanitize_text_field', - ]; - } + /** + * Default config of Field_Config. + * + * @since 0.1.0 + * @return array + */ + protected function defaultConfig() : array + { + return [ + 'callback' => [ $this, 'echoView' ], + 'sanitize_callback' => 'sanitize_text_field', + ]; + } } diff --git a/src/FunctionInvokerTrait.php b/src/FunctionInvokerTrait.php index 2bb1e74..9267406 100644 --- a/src/FunctionInvokerTrait.php +++ b/src/FunctionInvokerTrait.php @@ -29,67 +29,70 @@ * * @since 0.1.0 */ -trait FunctionInvokerTrait { - /** - * Check the accepted arguments for a given function and pass associative - * array values in the right order. - * - * @since 0.1.0 - * - * @param string $function Name of the function to invoke. - * @param ArrayObject $args Associative array object that contains the arguments. - * - * @return mixed Return value of the invoked function. - * @throws InvalidArgumentException If the function cannot be invoked. - */ - private function invoke_function( string $function, ArrayObject $args ) { - try { - $reflection = new ReflectionFunction( $function ); - $ordered_arguments = $this->parse_parameters( - $reflection->getParameters(), - $args->getArrayCopy() - ); +trait FunctionInvokerTrait +{ + /** + * Check the accepted arguments for a given function and pass associative + * array values in the right order. + * + * @since 0.1.0 + * + * @param string $function Name of the function to invoke. + * @param ArrayObject $args Associative array object that contains the arguments. + * + * @return mixed Return value of the invoked function. + * @throws InvalidArgumentException If the function cannot be invoked. + */ + private function invokeFunction(string $function, ArrayObject $args) + { + try { + $reflection = new ReflectionFunction($function); + $orderedArguments = $this->parseParameters( + $reflection->getParameters(), + $args->getArrayCopy() + ); - return $reflection->invokeArgs( $ordered_arguments ); - } catch ( Exception $exception ) { - throw new InvalidArgumentException( - sprintf( - 'Failed to invoke function "%1$s". Reason: "%2$s"', - $function, - $exception->getMessage() - ) - ); - } - } + return $reflection->invokeArgs($orderedArguments); + } catch (Exception $exception) { + throw new InvalidArgumentException( + sprintf( + 'Failed to invoke function "%1$s". Reason: "%2$s"', + $function, + $exception->getMessage() + ) + ); + } + } - /** - * Parse the parameters of a function to get the needed order. - * - * @since 0.1.0 - * - * @param ReflectionParameter[] $params The reflection parameters to parse. - * @param array $args The arguments to check against. - * - * @return array The correctly ordered arguments to pass - * to the reflected callable. - * @throws RuntimeException If a $param does not have a name() method. - */ - private function parse_parameters( array $params, array $args ) : array { - $ordered_args = []; - foreach ( $params as $param ) { - if ( ! $param instanceof ReflectionParameter ) { - throw new RuntimeException( - sprintf( - 'Parameter "%1$s" is not an instance of ReflectionParameter.', - $param - ) - ); - } - $ordered_args[] = array_key_exists( $param->name, $args ) - ? $args[ $param->name ] - : $param->getDefaultValue(); - } + /** + * Parse the parameters of a function to get the needed order. + * + * @since 0.1.0 + * + * @param ReflectionParameter[] $params The reflection parameters to parse. + * @param array $args The arguments to check against. + * + * @return array The correctly ordered arguments to pass + * to the reflected callable. + * @throws RuntimeException If a $param does not have a name() method. + */ + private function parseParameters(array $params, array $args) : array + { + $orderedArgs = []; + foreach ($params as $param) { + if (! $param instanceof ReflectionParameter) { + throw new RuntimeException( + sprintf( + 'Parameter "%1$s" is not an instance of ReflectionParameter.', + $param + ) + ); + } + $orderedArgs[] = array_key_exists($param->name, $args) + ? $args[ $param->name ] + : $param->getDefaultValue(); + } - return $ordered_args; - } + return $orderedArgs; + } } diff --git a/src/MenuPageConfig.php b/src/MenuPageConfig.php index 1cf916a..709a815 100644 --- a/src/MenuPageConfig.php +++ b/src/MenuPageConfig.php @@ -54,51 +54,55 @@ * * @since 0.1.0 */ -class MenuPageConfig extends Config { - use ViewEchoTrait; +class MenuPageConfig extends Config +{ + use ViewEchoTrait; - /** - * Menu_Page_Config constructor. - * - * @since 0.1.0 - * - * @param array $config Custom config array. - */ - public function __construct( array $config = [] ) { - parent::__construct( $config ); + /** + * Menu_Page_Config constructor. + * + * @since 0.1.0 + * + * @param array $config Custom config array. + */ + public function __construct(array $config = []) + { + parent::__construct($config); - // Determine which function to use: - // add_menu_page OR add_submenu_page. - $this->function_name = $this->function_name ?? $this->has_key( 'parent_slug' ) - ? 'add_submenu_page' - : 'add_menu_page'; - } + // Determine which function to use: + // add_menu_page OR add_submenu_page. + $this->function_name = $this->function_name ?? $this->hasKey('parent_slug') + ? 'add_submenu_page' + : 'add_menu_page'; + } - /** - * Url of this menu page. - * - * @since 0.3.0 - * - * @return string Admin URL link with menu slug appended. - */ - public function url() : string { - // TODO: It doesn't work for standard WordPress admin pages. - return admin_url( 'admin.php?page=' . $this->menu_slug ); - } + /** + * Url of this menu page. + * + * @since 0.3.0 + * + * @return string Admin URL link with menu slug appended. + */ + public function url() : string + { + // TODO: It doesn't work for standard WordPress admin pages. + return admin_url('admin.php?page=' . $this->menu_slug); + } - /** - * Default config of Menu_Page_Config. - * - * @since 0.1.0 - * - * @return array - * @throws \InvalidArgumentException If the partial is not supported. - */ - protected function default_config() : array { - return [ + /** + * Default config of Menu_Page_Config. + * + * @since 0.1.0 + * + * @return array + * @throws \InvalidArgumentException If the partial is not supported. + */ + protected function defaultConfig() : array + { + return [ 'capability' => 'manage_options', - 'view' => ViewFactory::build( 'tabbed-options-page' ), - 'function' => [ $this, 'echo_view' ], - ]; - } + 'view' => ViewFactory::build('tabbed-options-page'), + 'function' => [ $this, 'echoView' ], + ]; + } } diff --git a/src/MenuPages.php b/src/MenuPages.php index d9d7f23..2ed0f81 100644 --- a/src/MenuPages.php +++ b/src/MenuPages.php @@ -28,73 +28,78 @@ * don't have to deal with all the confusing callback code that the * WordPress Settings API forces you to use. */ -class MenuPages { - use FunctionInvokerTrait; +class MenuPages +{ + use FunctionInvokerTrait; - /** - * Array of Config instance. - * - * @since 0.1.0 - * - * @var ArrayObject[]; - */ - protected $menu_page_configs; + /** + * Array of Config instance. + * + * @since 0.1.0 + * + * @var ArrayObject[]; + */ + protected $menuPageConfigs; - /** - * Menu_Pages constructor. - * - * @since 0.1.0 - * - * @param ArrayObject[] $menu_page_configs Array of config objects that contains - * menu page configurations. - */ - public function __construct( array $menu_page_configs ) { - $this->menu_page_configs = $menu_page_configs; - } + /** + * Menu_Pages constructor. + * + * @since 0.1.0 + * + * @param ArrayObject[] $menuPageConfigs Array of config objects that contains + * menu page configurations. + */ + public function __construct(array $menuPageConfigs) + { + $this->menuPageConfigs = $menuPageConfigs; + } - /** - * Add the pages from the configuration objects to the WordPress admin - * backend. Parent pages are invoked first. - * - * @since 0.1.0 - * @return void - */ - public function admin_menu() { - // Parent pages must be added before submenu pages. - usort( $this->menu_page_configs, [ $this, 'compare_parent_slug' ] ); - array_walk( $this->menu_page_configs, [ $this, 'add_menu_page' ] ); - } + /** + * Add the pages from the configuration objects to the WordPress admin + * backend. Parent pages are invoked first. + * + * @since 0.1.0 + * @return void + */ + public function adminMenu() + { + // Parent pages must be added before submenu pages. + usort($this->menuPageConfigs, [ $this, 'compareParentSlug' ]); + array_walk($this->menuPageConfigs, [ $this, 'addMenuPage' ]); + } - /** - * Add a single page to the WordPress admin backend. - * - * @since 0.1.0 - * - * @param ArrayObject $menu_page_config Arguments for the menu page creation function. - * - * @return void - * @throws \InvalidArgumentException If the function cannot be invoked. - */ - protected function add_menu_page( ArrayObject $menu_page_config ) { - $menu_page_config->tabs = $this->menu_page_configs; - $this->invoke_function( $menu_page_config->function_name, $menu_page_config ); - } + /** + * Add a single page to the WordPress admin backend. + * + * @since 0.1.0 + * + * @param ArrayObject $menuPageConfig Arguments for the menu page creation function. + * + * @return void + * @throws \InvalidArgumentException If the function cannot be invoked. + */ + protected function addMenuPage(ArrayObject $menuPageConfig) + { + $menuPageConfig->tabs = $this->menuPageConfigs; + $this->invokeFunction($menuPageConfig->function_name, $menuPageConfig); + } - /** - * Compare two ArrayObject by their parent_slug. - * - * @since 0.5.1 - * @access private - * - * @param ArrayObject $first The first to be compared. - * @param ArrayObject $other The other to be compared. - * - * @return int - */ - private function compare_parent_slug( ArrayObject $first, ArrayObject $other ) : int { - $first_parent_slug = $first['parent_slug'] ?? null; - $other_parent_slug = $other['parent_slug'] ?? null; + /** + * Compare two ArrayObject by their parent_slug. + * + * @since 0.5.1 + * @access private + * + * @param ArrayObject $first The first to be compared. + * @param ArrayObject $other The other to be compared. + * + * @return int + */ + private function compareParentSlug(ArrayObject $first, ArrayObject $other) : int + { + $firstParentSlug = $first['parent_slug'] ?? null; + $otherParentSlug = $other['parent_slug'] ?? null; - return strcmp( $first_parent_slug, $other_parent_slug ); - } + return strcmp($firstParentSlug, $otherParentSlug); + } } diff --git a/src/OptionStore.php b/src/OptionStore.php index db3baab..e08b574 100644 --- a/src/OptionStore.php +++ b/src/OptionStore.php @@ -23,29 +23,31 @@ * * @since 0.5.0 */ -class OptionStore implements OptionStoreInterface { - /** - * Get an option value from database. - * - * Wrapper around the WordPress function `get_option`. - * - * @since 0.5.0 - * - * @param string $option_name Name of option to retrieve. - * Expected to not be SQL-escaped. - * @param string $key Array key of the option element. - * Also, the field ID. - * - * @return mixed - */ - public function get( string $option_name, string $key ) { - $option = get_option( $option_name, [] ); +class OptionStore implements OptionStoreInterface +{ + /** + * Get an option value from database. + * + * Wrapper around the WordPress function `get_option`. + * + * @since 0.5.0 + * + * @param string $option_name Name of option to retrieve. + * Expected to not be SQL-escaped. + * @param string $key Array key of the option element. + * Also, the field ID. + * + * @return mixed + */ + public function get(string $option_name, string $key) + { + $option = get_option($option_name, []); - if ( ! is_array( $option ) ) { - return $option; - } + if (! is_array($option)) { + return $option; + } - // TODO: Add filters and hooks. - return $option[ $key ] ?? false; - } + // TODO: Add filters and hooks. + return $option[ $key ] ?? false; + } } diff --git a/src/OptionStoreInterface.php b/src/OptionStoreInterface.php index 4243ff8..fecf801 100644 --- a/src/OptionStoreInterface.php +++ b/src/OptionStoreInterface.php @@ -23,18 +23,19 @@ * * @since 0.5.0 */ -interface OptionStoreInterface { - /** - * Get an option value. - * - * @since 0.5.0 - * - * @param string $option_name Name of option to retrieve. - * Expected to not be SQL-escaped. - * @param string $key Array key of the option element. - * Also, the field ID. - * - * @return mixed - */ - public function get( string $option_name, string $key ); +interface OptionStoreInterface +{ + /** + * Get an option value. + * + * @since 0.5.0 + * + * @param string $option_name Name of option to retrieve. + * Expected to not be SQL-escaped. + * @param string $key Array key of the option element. + * Also, the field ID. + * + * @return mixed + */ + public function get(string $option_name, string $key); } diff --git a/src/Sanitizer.php b/src/Sanitizer.php index 40310c3..6569bf1 100644 --- a/src/Sanitizer.php +++ b/src/Sanitizer.php @@ -19,48 +19,56 @@ * * @since 0.1.0 */ -final class Sanitizer { - /** - * Sanitize checkbox - * - * Sanitize any input other than '1', 1 or boolean true to empty string. - * - * @since 0.4.0 - * - * @param string $input User submitted value. - * - * @return string Empty string OR '1' - */ - public static function sanitize_checkbox( string $input ) : string { - $sanitized_input = sanitize_text_field( $input ); - if ( '1' !== $sanitized_input ) { - $sanitized_input = ''; - } +final class Sanitizer +{ + /** + * Sanitize checkbox + * + * Sanitize any input other than '1', 1 or boolean true to empty string. + * + * @since 0.4.0 + * + * @param string $input User submitted value. + * + * @return string Empty string OR '1' + */ + public static function sanitizeCheckbox(string $input) : string + { + $sanitized_input = sanitize_text_field($input); + if ('1' !== $sanitized_input) { + $sanitized_input = ''; + } - return $sanitized_input; - } + return $sanitized_input; + } - /** - * Sanitize email - * - * Strips out all characters that are not allowable in an email address. - * Add settings error if email is not valid. - * - * @since 0.1.0 - * - * @param string $input Input email. - * @param string $field_id ID of the settings field. - * - * @return string Valid email address OR empty string. - */ - public static function sanitize_email( string $input, string $field_id ) : string { + /** + * Sanitize email + * + * Strips out all characters that are not allowable in an email address. + * Add settings error if email is not valid. + * + * @since 0.1.0 + * + * @param string $input Input email. + * @param string $field_id ID of the settings field. + * + * @return string Valid email address OR empty string. + */ + public static function sanitizeEmail(string $input, string $field_id) : string + { - $sanitized_input = sanitize_email( $input ); - if ( ! is_email( $sanitized_input ) ) { - $error = __( 'Sorry, that isn’t a valid email address. Email addresses look like username@example.com.' ); - add_settings_error( $field_id, "invalid_$field_id", $error ); - } + $sanitized_input = sanitize_email($input); + if (! is_email($sanitized_input)) { + // @codingStandardsIgnoreStart + $error = __( + 'Sorry, that isn’t a valid email address. Email addresses look like username@example.com.', + 'wp-better-settings' + ); + // @codingStandardsIgnoreEnd + add_settings_error($field_id, "invalid_$field_id", $error); + } - return $sanitized_input; - } + return $sanitized_input; + } } diff --git a/src/SectionConfig.php b/src/SectionConfig.php index a1a2302..34619a8 100644 --- a/src/SectionConfig.php +++ b/src/SectionConfig.php @@ -41,55 +41,59 @@ * * @since 0.1.0 */ -class SectionConfig extends Config { - use ViewEchoTrait; +class SectionConfig extends Config +{ + use ViewEchoTrait; - /** - * Fields getter. - * - * @since 0.5.0 - * @return FieldConfig[] - * @throws UnexpectedValueException If fields is not Field_Config[]. - */ - public function get_fields() : array { - $this->validate_fields(); + /** + * Fields getter. + * + * @since 0.5.0 + * @return FieldConfig[] + * @throws UnexpectedValueException If fields is not Field_Config[]. + */ + public function getFields() : array + { + $this->validateFields(); - return $this->get_key( 'fields' ); - } + return $this->getKey('fields'); + } - /** - * Check the fields. - * - * @since 0.5.0 - * @access private - * @return void - * @throws UnexpectedValueException If fields is not Field_Config[]. - */ - private function validate_fields() { - $fields = $this->get_key( 'fields' ); - if ( ! is_array( $fields ) ) { - $error_message = 'Fields in class ' . __CLASS__ . ' must be an array.'; - throw new UnexpectedValueException( $error_message ); - } + /** + * Check the fields. + * + * @since 0.5.0 + * @access private + * @return void + * @throws UnexpectedValueException If fields is not Field_Config[]. + */ + private function validateFields() + { + $fields = $this->getKey('fields'); + if (! is_array($fields)) { + $error_message = 'Fields in class ' . __CLASS__ . ' must be an array.'; + throw new UnexpectedValueException($error_message); + } - array_walk( $fields, function ( $field ) { - if ( ! $field instanceof FieldConfig ) { - $error_message = 'Field items in class ' . __CLASS__ . ' must be instances of Field_Config.'; - throw new UnexpectedValueException( $error_message ); - } - } ); - } + array_walk($fields, function ($field) { + if (! $field instanceof FieldConfig) { + $error_message = 'Field items in class ' . __CLASS__ . ' must be instances of Field_Config.'; + throw new UnexpectedValueException($error_message); + } + }); + } - /** - * Default config of Section_Config. - * - * @since 0.1.0 - * @return array - */ - protected function default_config() : array { - return [ - 'view' => ViewFactory::build( 'section-description' ), - 'callback' => [ $this, 'echo_view' ], - ]; - } + /** + * Default config of Section_Config. + * + * @since 0.1.0 + * @return array + */ + protected function defaultConfig() : array + { + return [ + 'view' => ViewFactory::build('section-description'), + 'callback' => [ $this, 'echoView' ], + ]; + } } diff --git a/src/SettingConfig.php b/src/SettingConfig.php index c23e999..2f40bd2 100644 --- a/src/SettingConfig.php +++ b/src/SettingConfig.php @@ -33,129 +33,136 @@ * * @since 0.1.0 */ -class SettingConfig extends Config { - use ViewEchoTrait; - - /** - * Sanitize settings fields. - * - * @since 0.5.0 - * - * @param array $input The value entered in the field. - * - * @return array The sanitized values. - * @throws \UnexpectedValueException If fields is not Field_Config[]. - */ - public function call_field_sanitize_fun( array $input ) { - $field_ids = array_keys( $input ); - $field_ids = array_filter( $field_ids ); - $field_configs = $this->get_fields_by( $field_ids ); - - foreach ( $field_configs as $field_config ) { - $sanitize_callback = $field_config->get_key( 'sanitize_callback' ); - if ( ! is_callable( $sanitize_callback ) ) { - continue; - } - - $id = $field_config->get_key( 'id' ); - $input[ $id ] = $sanitize_callback( $input[ $id ], $id ); - } - - // Unset empty elements. - return array_filter( $input ); - } - - /** - * Get fields by ids. - * - * @since 0.5.0 - * @access private - * - * @param array $ids IDs of the fields to return. - * - * @return FieldConfig[] - * @throws \UnexpectedValueException If section.fields is not Field_Config[]. - */ - private function get_fields_by( array $ids ) : array { - $ids = array_filter( $ids ); - $all_fields = $this->get_fields(); - - return array_filter( $all_fields, function ( FieldConfig $field ) use ( $ids ) { - $id = $field->get_key( 'id' ); - - return in_array( $id, $ids, true ); - } ); - } - - /** - * Get all fields. - * - * @since 0.1.0 - * @return FieldConfig[] - * @throws \UnexpectedValueException If sections.fields is not Field_Config[]. - */ - public function get_fields() : array { - $sections = $this->get_sections(); - - $pluck = array_map( - function ( SectionConfig $section ) { - return $section->get_fields(); - }, - $sections - ); - - return call_user_func_array( 'array_merge', $pluck ); - } - - /** - * Sections getter. - * - * @since 0.5.0 - * @return SectionConfig[] - * @throws \UnexpectedValueException If sections is not Section_Config[]. - */ - public function get_sections() : array { - $this->validate_sections(); - - return $this->get_key( 'sections' ); - } - - /** - * Check the sections. - * - * @since 0.5.0 - * @access private - * @return void - * @throws UnexpectedValueException If fields is not Field_Config[]. - */ - private function validate_sections() { - $sections = $this->get_key( 'sections' ); - if ( ! is_array( $sections ) ) { - $error_message = 'Sections in class ' . __CLASS__ . ' must be an array.'; - throw new UnexpectedValueException( $error_message ); - } - - array_walk( $sections, function ( $section ) { - if ( ! $section instanceof SectionConfig ) { - $error_message = 'Section items in class ' . __CLASS__ . ' must be instances of Section_Config.'; - throw new UnexpectedValueException( $error_message ); - } - } ); - } - - /** - * Default config of Setting_Config. - * - * @since 0.1.0 - * @return array - */ - protected function default_config() : array { - return [ - 'view' => ViewFactory::build( 'section-description' ), - 'function' => [ $this, 'echo_view' ], +class SettingConfig extends Config +{ + use ViewEchoTrait; + + /** + * Sanitize settings fields. + * + * @since 0.5.0 + * + * @param array $input The value entered in the field. + * + * @return array The sanitized values. + * @throws \UnexpectedValueException If fields is not Field_Config[]. + */ + public function callFieldSanitizeFun(array $input) + { + $fieldIds = array_keys($input); + $fieldIds = array_filter($fieldIds); + $fieldConfigs = $this->getFieldsBy($fieldIds); + + foreach ($fieldConfigs as $fieldConfig) { + $sanitizeCallback = $fieldConfig->getKey('sanitize_callback'); + if (! is_callable($sanitizeCallback)) { + continue; + } + + $id = $fieldConfig->getKey('id'); + $input[ $id ] = $sanitizeCallback($input[ $id ], $id); + } + + // Unset empty elements. + return array_filter($input); + } + + /** + * Get fields by ids. + * + * @since 0.5.0 + * @access private + * + * @param array $ids IDs of the fields to return. + * + * @return FieldConfig[] + * @throws \UnexpectedValueException If section.fields is not Field_Config[]. + */ + private function getFieldsBy(array $ids) : array + { + $ids = array_filter($ids); + $allFields = $this->getFields(); + + return array_filter($allFields, function (FieldConfig $field) use ($ids) { + $id = $field->getKey('id'); + + return in_array($id, $ids, true); + }); + } + + /** + * Get all fields. + * + * @since 0.1.0 + * @return FieldConfig[] + * @throws \UnexpectedValueException If sections.fields is not Field_Config[]. + */ + public function getFields() : array + { + $sections = $this->getSections(); + + $pluck = array_map( + function (SectionConfig $section) { + return $section->getFields(); + }, + $sections + ); + + return array_merge(...$pluck); + } + + /** + * Sections getter. + * + * @since 0.5.0 + * @return SectionConfig[] + * @throws \UnexpectedValueException If sections is not Section_Config[]. + */ + public function getSections() : array + { + $this->validateSections(); + + return $this->getKey('sections'); + } + + /** + * Check the sections. + * + * @since 0.5.0 + * @access private + * @return void + * @throws UnexpectedValueException If fields is not Field_Config[]. + */ + private function validateSections() + { + $sections = $this->getKey('sections'); + if (! is_array($sections)) { + $errorMessage = 'Sections in class ' . __CLASS__ . ' must be an array.'; + throw new UnexpectedValueException($errorMessage); + } + + array_walk($sections, function ($section) { + if (! $section instanceof SectionConfig) { + $errorMessage = 'Section items in class ' . __CLASS__ . ' must be instances of Section_Config.'; + throw new UnexpectedValueException($errorMessage); + } + }); + } + + /** + * Default config of Setting_Config. + * + * @since 0.1.0 + * @return array + */ + protected function defaultConfig() : array + { + return [ + 'view' => ViewFactory::build('section-description'), + 'function' => [ $this, 'echoView' ], 'args' => [ - 'sanitize_callback' => [ $this, 'call_field_sanitize_fun' ], - ], - ]; - } + 'sanitize_callback' => [ $this, 'call_field_sanitize_fun' ], + ], + ]; + } } diff --git a/src/Settings.php b/src/Settings.php index 1285284..750c19f 100644 --- a/src/Settings.php +++ b/src/Settings.php @@ -28,112 +28,118 @@ * * @since 0.1.0 */ -class Settings { - use FunctionInvokerTrait; +class Settings +{ + use FunctionInvokerTrait; - /** - * Config instance. - * - * @since 0.1.0 - * @var ArrayObject[]; - */ - protected $setting_configs; + /** + * Option helper instance. + * + * @since 0.1.0 + * @var OptionStoreInterface; + */ + protected $optionHelper; - /** - * Option helper instance. - * - * @since 0.1.0 - * @var OptionStoreInterface; - */ - protected $option_helper; + /** + * Config instance. + * + * @since 0.1.0 + * @var ArrayObject[]; + */ + protected $settingConfigs; - /** - * Instantiate Settings object. - * - * @since 0.1.0 - * - * @param ArrayObject[] $setting_configs Config object that contains - * Settings configuration. - * @param OptionStoreInterface $option_helper Option helper. - */ - public function __construct( array $setting_configs, OptionStoreInterface $option_helper ) { - $this->setting_configs = $setting_configs; - $this->option_helper = $option_helper; - } + /** + * Instantiate Settings object. + * + * @since 0.1.0 + * + * @param ArrayObject[] $settingConfigs Config object that contains + * Settings configuration. + * @param OptionStoreInterface $optionHelper Option helper. + */ + public function __construct(array $settingConfigs, OptionStoreInterface $optionHelper) + { + $this->settingConfigs = $settingConfigs; + $this->optionHelper = $optionHelper; + } - /** - * Initialize the settings persistence. - * - * @since 0.1.0 - * @return void - */ - public function admin_init() { - array_walk( $this->setting_configs, [ $this, 'register_setting' ] ); - } + /** + * Initialize the settings persistence. + * + * @since 0.1.0 + * @return void + */ + public function adminInit() + { + array_walk($this->settingConfigs, [ $this, 'registerSetting' ]); + } - /** - * Register a single setting group. - * - * @since 0.1.0 - * - * @param ArrayObject $setting_config Arguments for the register_setting WP function. - * - * @return void - * @throws \InvalidArgumentException If register_setting cannot be invoked. - */ - protected function register_setting( ArrayObject $setting_config ) { - $this->invoke_function( 'register_setting', $setting_config ); + /** + * Add a single settings field. + * + * @since 0.1.0 + * + * @param ArrayObject $field_config Arguments for the add_settings_field WP function. + * @param string $_key [Unused] Key of the settings field. + * @param array $args Contains both page and section name. + * + * @return void + * @throws \InvalidArgumentException If add_settings_field cannot be invoked. + */ + protected function addField(ArrayObject $field_config, string $_key, array $args) + { + $field_config->page = $args['page']; + $field_config->section = $args['section']; + $field_config->option_name = $args['option_name']; + $field_config->value = $this->optionHelper->get( + $field_config->option_name, + $field_config->id + ); - // Prepare array to pass to array_walk as third parameter. - $args = []; - $args['option_name'] = $setting_config->option_name; + $this->invokeFunction('add_settings_field', $field_config); + } - array_walk( $setting_config->sections, [ $this, 'add_section' ], $args ); - } + /** + * Add a single settings section. + * + * @since 0.1.0 + * + * @param ArrayObject $sectionConfig Arguments for the add_settings_section WP function. + * @param string $_key [Unused] Key of the settings section. + * @param array $args Additional arguments to pass on. + * + * @return void + * @throws \InvalidArgumentException If add_settings_section cannot be invoked. + */ + protected function addSection(ArrayObject $sectionConfig, string $_key, array $args) + { + $this->invokeFunction('add_settings_section', $sectionConfig); - /** - * Add a single settings section. - * - * @since 0.1.0 - * - * @param ArrayObject $section_config Arguments for the add_settings_section WP function. - * @param string $_key [Unused] Key of the settings section. - * @param array $args Additional arguments to pass on. - * - * @return void - * @throws \InvalidArgumentException If add_settings_section cannot be invoked. - */ - protected function add_section( ArrayObject $section_config, string $_key, array $args ) { - $this->invoke_function( 'add_settings_section', $section_config ); + // Extend array to pass to array_walk as third parameter. + $args['page'] = $sectionConfig->page; + $args['section'] = $sectionConfig->id; - // Extend array to pass to array_walk as third parameter. - $args['page'] = $section_config->page; - $args['section'] = $section_config->id; + array_walk($sectionConfig->fields, [ $this, 'addField' ], $args); + } - array_walk( $section_config->fields, [ $this, 'add_field' ], $args ); - } + /** + * Register a single setting group. + * + * @since 0.1.0 + * + * @param ArrayObject $setting_config Arguments for the register_setting WP function. + * + * @return void + * @throws \InvalidArgumentException If register_setting cannot be invoked. + */ + protected function registerSetting(ArrayObject $setting_config) + { + $this->invokeFunction('register_setting', $setting_config); - /** - * Add a single settings field. - * - * @since 0.1.0 - * - * @param ArrayObject $field_config Arguments for the add_settings_field WP function. - * @param string $_key [Unused] Key of the settings field. - * @param array $args Contains both page and section name. - * - * @return void - * @throws \InvalidArgumentException If add_settings_field cannot be invoked. - */ - protected function add_field( ArrayObject $field_config, string $_key, array $args ) { - $field_config->page = $args['page']; - $field_config->section = $args['section']; - $field_config->option_name = $args['option_name']; - $field_config->value = $this->option_helper->get( - $field_config->option_name, - $field_config->id - ); + // Prepare array to pass to array_walk as third parameter. + $args = []; + $args['option_name'] = $setting_config->option_name; - $this->invoke_function( 'add_settings_field', $field_config ); - } + array_walk($setting_config->sections, [ $this, 'addSection' ], $args); + } } diff --git a/src/View.php b/src/View.php index 181eada..1c15982 100644 --- a/src/View.php +++ b/src/View.php @@ -21,116 +21,121 @@ * * @since 0.1.0 */ -class View implements ViewInterface { - /** - * Array of allowed tags to let through escaping. - * - * @since 0.1.0 - * @access private - * @var array - */ - private $allowed_tags; +class View implements ViewInterface +{ + /** + * Array of allowed tags to let through escaping. + * + * @since 0.1.0 + * @access private + * @var array + */ + private $allowedTags; - /** - * Filename of the PHP view to render. - * - * @since 0.1.0 - * @access private - * @var string - */ - private $filename; + /** + * Filename of the PHP view to render. + * + * @since 0.1.0 + * @access private + * @var string + */ + private $filename; - /** - * View constructor. - * - * @since 0.1.0 - * - * @param string $filename Filename of the PHP view to render. - * @param array $allowed_tags [Optional] Array of allowed tags to - * let through escaping functions. Set - * to sane defaults if none provided. - */ - public function __construct( string $filename, array $allowed_tags = [] ) { - $this->filename = $filename; - $this->allowed_tags = empty( $allowed_tags ) - ? $this->default_allowed_tags() - : $allowed_tags; - } + /** + * View constructor. + * + * @since 0.1.0 + * + * @param string $filename Filename of the PHP view to render. + * @param array $allowedTags [Optional] Array of allowed tags to + * let through escaping functions. Set + * to sane defaults if none provided. + */ + public function __construct(string $filename, array $allowedTags = []) + { + $this->filename = $filename; + $this->allowedTags = empty($allowedTags) + ? $this->defaultAllowedTags() + : $allowedTags; + } - /** - * Prepare an array of allowed tags by adding form elements to the existing - * array. - * - * This makes sure that the basic form elements always pass through the - * escaping functions. - * - * @since 0.1.0 - * @access private - * @return array Modified tags array. - */ - private function default_allowed_tags() : array { - $form_tags = [ - 'form' => [ - 'id' => true, - 'class' => true, - 'action' => true, - 'method' => true, - ], - 'input' => [ - 'id' => true, - 'class' => true, - 'type' => true, - 'name' => true, - 'value' => true, - 'checked' => true, - 'disabled' => true, - 'aria-describedby' => true, - ], - 'textarea' => [ - 'aria-describedby' => true, - 'col' => true, - 'disabled' => true, - 'row' => true, - ], - ]; + /** + * Prepare an array of allowed tags by adding form elements to the existing + * array. + * + * This makes sure that the basic form elements always pass through the + * escaping functions. + * + * @since 0.1.0 + * @access private + * @return array Modified tags array. + */ + private function defaultAllowedTags() : array + { + $formTags = [ + 'form' => [ + 'id' => true, + 'class' => true, + 'action' => true, + 'method' => true, + ], + 'input' => [ + 'id' => true, + 'class' => true, + 'type' => true, + 'name' => true, + 'value' => true, + 'checked' => true, + 'disabled' => true, + 'aria-describedby' => true, + ], + 'textarea' => [ + 'aria-describedby' => true, + 'col' => true, + 'disabled' => true, + 'row' => true, + ], + ]; - return array_replace_recursive( wp_kses_allowed_html( 'post' ), $form_tags ); - } + return array_replace_recursive(wp_kses_allowed_html('post'), $formTags); + } - /** - * Echo a given view safely. - * - * @since 0.2.0 - * - * @param mixed $context Context ArrayObject for which to render the view. - * - * @return void - */ - public function echo_kses( $context ) { - echo wp_kses( - $this->render( $context ), - $this->allowed_tags - ); - } + /** + * Echo a given view safely. + * + * @since 0.2.0 + * + * @param mixed $context Context ArrayObject for which to render the view. + * + * @return void + */ + public function echoKses($context) + { + echo wp_kses( + $this->render($context), + $this->allowedTags + ); + } - /** - * Render the associated view as string. - * - * @see https://github.com/Medium/medium-wordpress-plugin/blob/c31713968990bab5d83db68cf486953ea161a009/lib/medium-view.php - * @since 0.1.0 - * - * @param mixed $context Context object to be passed into view partial. - * - * @return string HTML string. - */ - public function render( $context ) : string { - if ( ! is_readable( $this->filename ) ) { - return ''; - } + /** + * Render the associated view as string. + * + * @see https://github.com/Medium/medium-wordpress-plugin/blob/c31713968990bab5d83db68cf486953ea161a009/lib/medium-view.php + * @since 0.1.0 + * + * @param mixed $context Context object to be passed into view partial. + * + * @return string HTML string. + */ + public function render($context) : string + { + if (! is_readable($this->filename)) { + return ''; + } - ob_start(); - include $this->filename; + ob_start(); + include $this->filename; - return ob_get_clean(); - } + return ob_get_clean(); + } } diff --git a/src/ViewEchoTrait.php b/src/ViewEchoTrait.php index 162a982..f2e474d 100644 --- a/src/ViewEchoTrait.php +++ b/src/ViewEchoTrait.php @@ -24,23 +24,25 @@ * @property ViewInterface|string $view View_Interface object to render. * Or, string of path to view partial. */ -trait ViewEchoTrait { - /** - * Echo the view safely. - * - * @since 0.5.1 - * @return void - */ - public function echo_view() { - $view = $this->view; - if ( is_string( $view ) ) { - $view = new View( $view ); - } +trait ViewEchoTrait +{ + /** + * Echo the view safely. + * + * @since 0.5.1 + * @return void + */ + public function echoView() + { + $view = $this->view; + if (is_string($view)) { + $view = new View($view); + } - if ( ! $view instanceof ViewInterface ) { - return; - } + if (! $view instanceof ViewInterface) { + return; + } - $view->echo_kses( $this ); - } + $view->echoKses($this); + } } diff --git a/src/ViewFactory.php b/src/ViewFactory.php index 4d6ebc0..1819354 100644 --- a/src/ViewFactory.php +++ b/src/ViewFactory.php @@ -23,49 +23,51 @@ * * @since 0.1.0 */ -final class ViewFactory { - /** - * Relative path to built-in view partials. - * - * @since 0.1.0 - * @var array - */ - const PARTIALS = [ - 'basic-options-page' => 'partials/basic-options-page.php', - 'section-description' => 'partials/section-description.php', - 'checkbox-field' => 'partials/checkbox-field.php', - 'email-field' => 'partials/email-field.php', - 'tabbed-options-page' => 'partials/tabbed-options-page.php', - 'text-field' => 'partials/text-field.php', - 'textarea-field' => 'partials/textarea-field.php', - 'url-field' => 'partials/url-field.php', - ]; +final class ViewFactory +{ + /** + * Relative path to built-in view partials. + * + * @since 0.1.0 + * @var array + */ + const PARTIALS = [ + 'basic-options-page' => 'partials/basic-options-page.php', + 'section-description' => 'partials/section-description.php', + 'checkbox-field' => 'partials/checkbox-field.php', + 'email-field' => 'partials/email-field.php', + 'tabbed-options-page' => 'partials/tabbed-options-page.php', + 'text-field' => 'partials/text-field.php', + 'textarea-field' => 'partials/textarea-field.php', + 'url-field' => 'partials/url-field.php', + ]; - /** - * Built a View object for one of the built-in field types. - * - * @since 0.1.0 - * - * @param string $type Type of the partial. Must be one of - * the built-in partial. - * - * @return View View object for the partial. - * - * @throws InvalidArgumentException If the partial is not supported. - */ - public static function build( string $type ) : View { - if ( ! array_key_exists( $type, self::PARTIALS ) ) { - $error_message = sprintf( - '%1$s: Partial for "%2$s" not found. Build-in partials include "%3$s".', - __CLASS__, - $type, - implode( ', ', array_keys( self::PARTIALS ) ) - ); - throw new InvalidArgumentException( $error_message ); - } + /** + * Built a View object for one of the built-in field types. + * + * @since 0.1.0 + * + * @param string $type Type of the partial. Must be one of + * the built-in partial. + * + * @return View View object for the partial. + * + * @throws InvalidArgumentException If the partial is not supported. + */ + public static function build(string $type) : View + { + if (! array_key_exists($type, self::PARTIALS)) { + $errorMessage = sprintf( + '%1$s: Partial for "%2$s" not found. Build-in partials include "%3$s".', + __CLASS__, + $type, + implode(', ', array_keys(self::PARTIALS)) + ); + throw new InvalidArgumentException($errorMessage); + } - return new View( - plugin_dir_path( __FILE__ ) . self::PARTIALS[ $type ] - ); - } + return new View( + plugin_dir_path(__FILE__) . self::PARTIALS[ $type ] + ); + } } diff --git a/src/ViewInterface.php b/src/ViewInterface.php index a064c17..6d77d6a 100644 --- a/src/ViewInterface.php +++ b/src/ViewInterface.php @@ -21,15 +21,16 @@ * * @since 0.2.0 */ -interface ViewInterface { - /** - * Echo a given view safely. - * - * @since 0.2.0 - * - * @param mixed $context Context ArrayObject for which to render the view. - * - * @return void - */ - public function echo_kses( $context ); +interface ViewInterface +{ + /** + * Echo a given view safely. + * + * @since 0.2.0 + * + * @param mixed $context Context ArrayObject for which to render the view. + * + * @return void + */ + public function echoKses($context); } diff --git a/src/partials/basic-options-page.php b/src/partials/basic-options-page.php index 3e3c24e..9f553e3 100644 --- a/src/partials/basic-options-page.php +++ b/src/partials/basic-options-page.php @@ -16,12 +16,12 @@ /* @var \ArrayObject $context Context passed through from Menu_Pages class. */ -$snakecased_menu_slug = str_replace( '-', '_', $context->menu_slug ); +$snakecased_menu_slug = str_replace('-', '_', $context->menu_slug); -do_action( $snakecased_menu_slug . '_before_page_title' ); +do_action($snakecased_menu_slug . '_before_page_title'); -echo '

' . esc_html( $context->page_title ) . '

'; +echo '

' . esc_html($context->page_title) . '

'; -do_action( $snakecased_menu_slug . '_after_page_title' ); +do_action($snakecased_menu_slug . '_after_page_title'); include __DIR__ . '/options-form.php'; diff --git a/src/partials/checkbox-field.php b/src/partials/checkbox-field.php index c720cf3..02f5e64 100644 --- a/src/partials/checkbox-field.php +++ b/src/partials/checkbox-field.php @@ -17,16 +17,16 @@ /* @var \ArrayObject $context Context passed through from Settings class. */ echo '
'; -echo '' . esc_html( $context->title ) . ''; +echo '' . esc_html($context->title) . ''; -echo '