├── .prettierrc
├── .wp-env.json
├── .vscode
└── settings.json
├── src
├── index.js
├── style.scss
└── components
│ ├── Panel.js
│ └── SettingsPage.js
├── readme.txt
├── .editorconfig
├── .gitignore
├── package.json
├── example-wp-settings.php
├── .stylelintrc.json
├── readme.md
└── inc
└── class-example-wp-settings.php
/.prettierrc:
--------------------------------------------------------------------------------
1 | "@wordpress/prettier-config"
2 |
--------------------------------------------------------------------------------
/.wp-env.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["."]
3 | }
4 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "[scss]": {
3 | "editor.defaultFormatter": "esbenp.prettier-vscode",
4 | "editor.formatOnSave": true
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import { createRoot } from '@wordpress/element';
2 | import SettingsPage from './components/SettingsPage';
3 |
4 | import './style.scss';
5 |
6 | let root = createRoot( document.getElementById( 'root' ) );
7 | root.render( );
8 |
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 | === Example WP Settings ===
2 | Contributors: bacoords
3 | Tags: block
4 | Tested up to: 6.1
5 | Stable tag: 0.1.0
6 | License: GPL-2.0-or-later
7 | License URI: https://www.gnu.org/licenses/gpl-2.0.html
8 |
9 | Example settings page scaffolded with Create Block tool.
10 |
--------------------------------------------------------------------------------
/src/style.scss:
--------------------------------------------------------------------------------
1 | .example-wp-settings {
2 | max-width: 780px;
3 | h1 {
4 | text-align: center;
5 | }
6 | .example-wp-settings-tab-panel {
7 | .components-tab-panel__tabs {
8 | justify-content: center;
9 | border-bottom: 1px solid #ddd;
10 | }
11 | }
12 |
13 | .example-wp-settings-field-group {
14 | margin-top: 2rem;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # This file is for unifying the coding style for different editors and IDEs
2 | # editorconfig.org
3 |
4 | # WordPress Coding Standards
5 | # https://make.wordpress.org/core/handbook/coding-standards/
6 |
7 | root = true
8 |
9 | [*]
10 | charset = utf-8
11 | end_of_line = lf
12 | insert_final_newline = true
13 | trim_trailing_whitespace = true
14 | indent_style = tab
15 |
16 | [*.{yml,yaml}]
17 | indent_style = space
18 | indent_size = 2
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Coverage directory used by tools like istanbul
9 | coverage
10 |
11 | # Compiled binary addons (https://nodejs.org/api/addons.html)
12 | build/Release
13 |
14 | # Dependency directories
15 | node_modules/
16 |
17 | # Optional npm cache directory
18 | .npm
19 |
20 | # Optional eslint cache
21 | .eslintcache
22 |
23 | # Output of `npm pack`
24 | *.tgz
25 |
26 | # Output of `wp-scripts plugin-zip`
27 | *.zip
28 |
29 | # dotenv environment variables file
30 | .env
31 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example-wp-settings",
3 | "version": "0.1.0",
4 | "description": "Example WordPress settings page.",
5 | "author": "The WordPress Contributors",
6 | "license": "GPL-2.0-or-later",
7 | "main": "build/index.js",
8 | "scripts": {
9 | "build": "wp-scripts build",
10 | "format": "wp-scripts format",
11 | "lint:css": "wp-scripts lint-style",
12 | "lint:js": "wp-scripts lint-js",
13 | "packages-update": "wp-scripts packages-update",
14 | "plugin-zip": "wp-scripts plugin-zip",
15 | "start": "wp-scripts start",
16 | "env": "wp-env"
17 | },
18 | "devDependencies": {
19 | "@wordpress/scripts": "^26.17.0"
20 | },
21 | "dependencies": {
22 | "@wordpress/env": "^8.12.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/example-wp-settings.php:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 | ## Development
9 |
10 | This plugin was scaffolded with [@wordpress/create-block](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-create-block/). If you'd like to develop from this repository, first install all of the dependencies:
11 |
12 | `npm install`
13 |
14 | Then run the build process in a watch mode:
15 |
16 | `npm start`
17 |
18 | ## Running Locally
19 |
20 | To use the included local environment, make sure Docker is running and then run the following command:
21 |
22 | `npm run env start`
23 |
24 | and visit [http://localhost:8888/wp-admin](http://localhost:8888/wp-admin).
25 |
26 | You should be able to log in with Username: `admin` and Password: `password`.
27 |
28 | [Learn more about wp-env](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/).
29 |
--------------------------------------------------------------------------------
/src/components/Panel.js:
--------------------------------------------------------------------------------
1 | import { __ } from '@wordpress/i18n';
2 | import { Flex, FlexItem, TextControl } from '@wordpress/components';
3 |
4 | import { useDispatch, useSelect } from '@wordpress/data';
5 | import { store as coreStore } from '@wordpress/core-data';
6 |
7 | function Panel() {
8 | // Get the settings from the store.
9 | const { record: settings, hasResolved } = useSelect( ( select ) => {
10 | return {
11 | record: select( coreStore ).getEditedEntityRecord( 'root', 'site' ),
12 | hasResolved: select( coreStore ).hasFinishedResolution(
13 | 'getEditedEntityRecord',
14 | [ 'root', 'site' ]
15 | ),
16 | };
17 | } );
18 |
19 | // We'll use these functions to save the settings to the store.
20 | const { editEntityRecord } = useDispatch( coreStore );
21 |
22 | if ( ! hasResolved ) {
23 | return null;
24 | }
25 |
26 | // This will save settings the settings to the local state only.
27 | const updateOptions = ( key, value ) => {
28 | editEntityRecord( 'root', 'site', undefined, {
29 | wpdev_account_settings: {
30 | ...settings.wpdev_account_settings,
31 | [ key ]: value,
32 | },
33 | } );
34 | };
35 |
36 | return (
37 |
42 |
43 | {
48 | updateOptions( 'account_number', value );
49 | } }
50 | />
51 |
52 |
53 | {
58 | updateOptions( 'account_key', value );
59 | } }
60 | />
61 |
62 |
63 | );
64 | }
65 |
66 | export default Panel;
67 |
--------------------------------------------------------------------------------
/src/components/SettingsPage.js:
--------------------------------------------------------------------------------
1 | import { __ } from '@wordpress/i18n';
2 | import { useState, useEffect } from '@wordpress/element';
3 | import {
4 | Card,
5 | CardBody,
6 | CardDivider,
7 | Flex,
8 | FlexItem,
9 | Button,
10 | Snackbar,
11 | TabPanel,
12 | } from '@wordpress/components';
13 |
14 | import { useDispatch, useSelect } from '@wordpress/data';
15 | import { store as coreStore } from '@wordpress/core-data';
16 |
17 | import Panel from './Panel';
18 |
19 | function SettingsPage() {
20 | // Get the settings from the store.
21 | const { record: settings, hasResolved } = useSelect( ( select ) => {
22 | return {
23 | record: select( coreStore ).getEditedEntityRecord( 'root', 'site' ),
24 | hasResolved: select( coreStore ).hasFinishedResolution(
25 | 'getEditedEntityRecord',
26 | [ 'root', 'site' ]
27 | ),
28 | };
29 | } );
30 |
31 | // We'll use these functions to save the settings to the store.
32 | const { saveEntityRecord } = useDispatch( coreStore );
33 |
34 | // State to show a success message when the settings are saved.
35 | const [ success, setSuccess ] = useState( false );
36 |
37 | // State to keep track of which tab is active.
38 | const [ activeTab, setActiveTab ] = useState( 'panel' );
39 |
40 | // If the settings haven't been loaded yet, we'll return null.
41 | // This needs to happen after all the hooks are called.
42 | if ( ! hasResolved ) {
43 | return null;
44 | }
45 | // In the block editor, saving to the database happens automatically when you publish or update a post.
46 | // In the our settings page, you would need to add a separate button to save the settings.
47 | const saveOptions = ( event ) => {
48 | event.preventDefault();
49 | saveEntityRecord( 'root', 'site', {
50 | wpdev_account_settings: settings.wpdev_account_settings,
51 | } ).then( ( response ) => {
52 | setSuccess( true );
53 | console.log( response );
54 | } );
55 | };
56 |
57 | return (
58 |
104 | );
105 | }
106 |
107 | export default SettingsPage;
108 |
--------------------------------------------------------------------------------
/inc/class-example-wp-settings.php:
--------------------------------------------------------------------------------
1 |
59 |
62 | id ) {
77 | return;
78 | }
79 |
80 | // Enqueue the styles for the core components library.
81 | wp_enqueue_style( 'global' );
82 | wp_enqueue_style( 'wp-edit-post' );
83 |
84 | // Our build processs generates a `index.asset.php` file for each entry point.
85 | $asset_file = include EXAMPLE_WP_SETTINGS_PATH . '/build/index.asset.php';
86 |
87 | // Enqueue the admin page script and its dependencies.
88 | wp_enqueue_script( 'example-wp-settings-admin-page', EXAMPLE_WP_SETTINGS_URL . '/build/index.js', $asset_file['dependencies'], $asset_file['version'], true );
89 |
90 | // Enqueue the admin page styles.
91 | wp_enqueue_style( 'example-wp-settings-admin-page', EXAMPLE_WP_SETTINGS_URL . '/build/style-index.css', array(), $asset_file['version'] );
92 | }
93 |
94 |
95 |
96 |
97 |
98 | /**
99 | * Register our custom settings handler.
100 | *
101 | * @return void
102 | */
103 | public static function register_custom_settings() {
104 |
105 | // Register our custom setting.
106 | register_setting(
107 | 'wpdev',
108 | 'wpdev_account_settings',
109 | array(
110 | 'type' => 'object', // Our setting is an object that could contain multiple values.
111 | 'description' => 'Account Settings for our API.',
112 | 'sanitize_callback' => array( get_class(), 'sanitize_callback' ),
113 | 'default' => array( // Default values for our setting.
114 | 'account_number' => '',
115 | 'account_key' => '',
116 | ),
117 | 'show_in_rest' => array(
118 | 'schema' => array(
119 | 'type' => 'object',
120 | 'properties' => array(
121 | 'account_number' => array( // Schema for our 'account_number'.
122 | 'type' => 'string',
123 | ),
124 | 'account_key' => array( // Schema for our 'account_key'.
125 | 'type' => 'string',
126 | ),
127 | ),
128 | ),
129 | ),
130 | )
131 | );
132 | }
133 |
134 |
135 | /**
136 | * Sanitize our settings.
137 | *
138 | * @param array $settings The settings to sanitize.
139 | * @return array
140 | */
141 | public static function sanitize_callback( $settings ) {
142 | // Sanitize our 'account_number'.
143 | $settings['account_number'] = sanitize_text_field( $settings['account_number'] );
144 | // Sanitize our 'account_key'.
145 | $settings['account_key'] = sanitize_text_field( $settings['account_key'] );
146 | return $settings;
147 | }
148 | }
149 |
--------------------------------------------------------------------------------