@mytechtoday/augment-extensions 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/augment-extensions/domain-rules/wordpress/README.md +163 -0
- package/augment-extensions/domain-rules/wordpress/module.json +32 -0
- package/augment-extensions/domain-rules/wordpress/rules/coding-standards.md +617 -0
- package/augment-extensions/domain-rules/wordpress/rules/directory-structure.md +270 -0
- package/augment-extensions/domain-rules/wordpress/rules/file-patterns.md +423 -0
- package/augment-extensions/domain-rules/wordpress/rules/gutenberg-blocks.md +493 -0
- package/augment-extensions/domain-rules/wordpress/rules/performance.md +568 -0
- package/augment-extensions/domain-rules/wordpress/rules/plugin-development.md +510 -0
- package/augment-extensions/domain-rules/wordpress/rules/project-detection.md +251 -0
- package/augment-extensions/domain-rules/wordpress/rules/rest-api.md +501 -0
- package/augment-extensions/domain-rules/wordpress/rules/security.md +564 -0
- package/augment-extensions/domain-rules/wordpress/rules/theme-development.md +388 -0
- package/augment-extensions/domain-rules/wordpress/rules/woocommerce.md +441 -0
- package/augment-extensions/domain-rules/wordpress-plugin/README.md +139 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/ajax-plugin.md +1599 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/custom-post-type-plugin.md +1727 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block-plugin.md +428 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block.md +422 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/mvc-plugin.md +1623 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/object-oriented-plugin.md +1343 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/rest-endpoint.md +734 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/settings-page-plugin.md +1350 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/simple-procedural-plugin.md +503 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/singleton-plugin.md +971 -0
- package/augment-extensions/domain-rules/wordpress-plugin/module.json +53 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/activation-hooks.md +770 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/admin-interface.md +874 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/ajax-handlers.md +629 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/asset-management.md +559 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/context-providers.md +709 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/cron-jobs.md +736 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/database-management.md +1057 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/documentation-standards.md +463 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/frontend-functionality.md +478 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/gutenberg-blocks.md +818 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/internationalization.md +416 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/migration.md +667 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/performance-optimization.md +878 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-architecture.md +693 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-structure.md +352 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/rest-api.md +818 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/scaffolding-workflow.md +624 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/security-best-practices.md +866 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/testing-patterns.md +1165 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/testing.md +414 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/vscode-integration.md +751 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/woocommerce-integration.md +949 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/wordpress-org-submission.md +458 -0
- package/augment-extensions/examples/gutenberg-block-plugin/README.md +101 -0
- package/augment-extensions/examples/gutenberg-block-plugin/examples/testimonial-block.md +428 -0
- package/augment-extensions/examples/gutenberg-block-plugin/module.json +40 -0
- package/augment-extensions/examples/rest-api-plugin/README.md +98 -0
- package/augment-extensions/examples/rest-api-plugin/examples/task-manager-api.md +1299 -0
- package/augment-extensions/examples/rest-api-plugin/module.json +40 -0
- package/augment-extensions/examples/woocommerce-extension/README.md +98 -0
- package/augment-extensions/examples/woocommerce-extension/examples/product-customizer.md +763 -0
- package/augment-extensions/examples/woocommerce-extension/module.json +40 -0
- package/augment-extensions/workflows/wordpress-plugin/README.md +232 -0
- package/augment-extensions/workflows/wordpress-plugin/ai-prompts.md +839 -0
- package/augment-extensions/workflows/wordpress-plugin/bead-decomposition-patterns.md +854 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/complete-plugin-example.md +540 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/custom-post-type-example.md +1083 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/feature-addition-workflow.md +669 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/plugin-creation-workflow.md +597 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/secure-form-handler-example.md +925 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/security-audit-workflow.md +752 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/wordpress-org-submission-workflow.md +773 -0
- package/augment-extensions/workflows/wordpress-plugin/module.json +49 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/best-practices.md +942 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/development-workflow.md +702 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/submission-workflow.md +728 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/testing-workflow.md +775 -0
- package/cli/dist/cli.js +5 -1
- package/cli/dist/cli.js.map +1 -1
- package/cli/dist/commands/show.d.ts.map +1 -1
- package/cli/dist/commands/show.js +41 -0
- package/cli/dist/commands/show.js.map +1 -1
- package/modules.md +52 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1350 @@
|
|
|
1
|
+
# Settings Page Plugin Example
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This example demonstrates a complete **Settings Page Plugin** with admin menu, settings registration, sections, fields, validation, sanitization, and proper security implementation.
|
|
6
|
+
|
|
7
|
+
**Complexity**: Medium
|
|
8
|
+
**File Count**: 5-10 files
|
|
9
|
+
**Team Size**: 1-2 developers
|
|
10
|
+
**Use Case**: Plugin configuration, site settings, feature toggles, API integrations
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Complete Plugin: "Site Settings Manager"
|
|
15
|
+
|
|
16
|
+
A comprehensive settings management plugin demonstrating WordPress Settings API, custom admin pages, field types, validation, and security best practices.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Directory Structure
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
site-settings-manager/
|
|
24
|
+
├── site-settings-manager.php # Main plugin file
|
|
25
|
+
├── uninstall.php # Uninstall cleanup
|
|
26
|
+
├── readme.txt # WordPress.org readme
|
|
27
|
+
├── includes/
|
|
28
|
+
│ ├── class-settings-page.php # Settings page class
|
|
29
|
+
│ ├── class-settings-fields.php # Field rendering
|
|
30
|
+
│ └── class-settings-validator.php # Validation logic
|
|
31
|
+
├── admin/
|
|
32
|
+
│ ├── css/
|
|
33
|
+
│ │ └── admin.css # Admin styles
|
|
34
|
+
│ ├── js/
|
|
35
|
+
│ │ └── admin.js # Admin scripts
|
|
36
|
+
│ └── views/
|
|
37
|
+
│ ├── settings-page.php # Main settings view
|
|
38
|
+
│ └── settings-sidebar.php # Sidebar view
|
|
39
|
+
└── assets/
|
|
40
|
+
└── images/
|
|
41
|
+
└── icon.png # Plugin icon
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Main Plugin File
|
|
47
|
+
|
|
48
|
+
### File: `site-settings-manager.php`
|
|
49
|
+
|
|
50
|
+
```php
|
|
51
|
+
<?php
|
|
52
|
+
/**
|
|
53
|
+
* Plugin Name: Site Settings Manager
|
|
54
|
+
* Plugin URI: https://example.com/site-settings-manager
|
|
55
|
+
* Description: Complete settings management with validation, sanitization, and security
|
|
56
|
+
* Version: 1.0.0
|
|
57
|
+
* Author: Your Name
|
|
58
|
+
* Author URI: https://example.com
|
|
59
|
+
* License: GPL-2.0+
|
|
60
|
+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
|
|
61
|
+
* Text Domain: site-settings-manager
|
|
62
|
+
* Domain Path: /languages
|
|
63
|
+
*
|
|
64
|
+
* @package Site_Settings_Manager
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
// Exit if accessed directly
|
|
68
|
+
if (!defined('ABSPATH')) {
|
|
69
|
+
exit;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Define plugin constants
|
|
73
|
+
define('SSM_VERSION', '1.0.0');
|
|
74
|
+
define('SSM_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
|
75
|
+
define('SSM_PLUGIN_URL', plugin_dir_url(__FILE__));
|
|
76
|
+
define('SSM_PLUGIN_FILE', __FILE__);
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Autoloader
|
|
80
|
+
*/
|
|
81
|
+
spl_autoload_register(function ($class) {
|
|
82
|
+
$prefix = 'SSM_';
|
|
83
|
+
|
|
84
|
+
if (strpos($class, $prefix) !== 0) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
$class_name = str_replace($prefix, '', $class);
|
|
89
|
+
$class_file = 'class-' . str_replace('_', '-', strtolower($class_name)) . '.php';
|
|
90
|
+
|
|
91
|
+
$file = SSM_PLUGIN_DIR . 'includes/' . $class_file;
|
|
92
|
+
if (file_exists($file)) {
|
|
93
|
+
require $file;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Activation hook
|
|
99
|
+
*/
|
|
100
|
+
register_activation_hook(__FILE__, function() {
|
|
101
|
+
// Set default options
|
|
102
|
+
$defaults = array(
|
|
103
|
+
'ssm_site_title' => get_bloginfo('name'),
|
|
104
|
+
'ssm_site_description' => get_bloginfo('description'),
|
|
105
|
+
'ssm_enable_feature' => false,
|
|
106
|
+
'ssm_api_key' => '',
|
|
107
|
+
'ssm_items_per_page' => 10,
|
|
108
|
+
'ssm_theme_color' => '#0073aa',
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
foreach ($defaults as $key => $value) {
|
|
112
|
+
if (get_option($key) === false) {
|
|
113
|
+
add_option($key, $value);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Deactivation hook
|
|
120
|
+
*/
|
|
121
|
+
register_deactivation_hook(__FILE__, function() {
|
|
122
|
+
// Cleanup if needed
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Initialize the plugin
|
|
127
|
+
*/
|
|
128
|
+
function run_site_settings_manager() {
|
|
129
|
+
// Initialize settings page
|
|
130
|
+
if (is_admin()) {
|
|
131
|
+
SSM_Settings_Page::init();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Load text domain
|
|
135
|
+
add_action('plugins_loaded', 'ssm_load_textdomain');
|
|
136
|
+
|
|
137
|
+
// Enqueue admin assets
|
|
138
|
+
add_action('admin_enqueue_scripts', 'ssm_enqueue_admin_assets');
|
|
139
|
+
}
|
|
140
|
+
add_action('plugins_loaded', 'run_site_settings_manager');
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Load plugin text domain
|
|
144
|
+
*/
|
|
145
|
+
function ssm_load_textdomain() {
|
|
146
|
+
load_plugin_textdomain(
|
|
147
|
+
'site-settings-manager',
|
|
148
|
+
false,
|
|
149
|
+
dirname(plugin_basename(SSM_PLUGIN_FILE)) . '/languages/'
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Enqueue admin assets
|
|
155
|
+
*/
|
|
156
|
+
function ssm_enqueue_admin_assets($hook) {
|
|
157
|
+
// Only load on our settings page
|
|
158
|
+
if ('settings_page_site-settings-manager' !== $hook) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
wp_enqueue_style(
|
|
163
|
+
'ssm-admin',
|
|
164
|
+
SSM_PLUGIN_URL . 'admin/css/admin.css',
|
|
165
|
+
array(),
|
|
166
|
+
SSM_VERSION
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
wp_enqueue_script(
|
|
170
|
+
'ssm-admin',
|
|
171
|
+
SSM_PLUGIN_URL . 'admin/js/admin.js',
|
|
172
|
+
array('jquery', 'wp-color-picker'),
|
|
173
|
+
SSM_VERSION,
|
|
174
|
+
true
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
// Enqueue color picker
|
|
178
|
+
wp_enqueue_style('wp-color-picker');
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Settings Page Class
|
|
185
|
+
|
|
186
|
+
### File: `includes/class-settings-page.php`
|
|
187
|
+
|
|
188
|
+
```php
|
|
189
|
+
<?php
|
|
190
|
+
/**
|
|
191
|
+
* Settings page class
|
|
192
|
+
*
|
|
193
|
+
* @package Site_Settings_Manager
|
|
194
|
+
*/
|
|
195
|
+
|
|
196
|
+
class SSM_Settings_Page {
|
|
197
|
+
/**
|
|
198
|
+
* Settings page slug
|
|
199
|
+
*/
|
|
200
|
+
const PAGE_SLUG = 'site-settings-manager';
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Option group
|
|
204
|
+
*/
|
|
205
|
+
const OPTION_GROUP = 'ssm_settings_group';
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Initialize
|
|
209
|
+
*/
|
|
210
|
+
public static function init() {
|
|
211
|
+
add_action('admin_menu', array(__CLASS__, 'add_admin_menu'));
|
|
212
|
+
add_action('admin_init', array(__CLASS__, 'register_settings'));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Add admin menu
|
|
217
|
+
*/
|
|
218
|
+
public static function add_admin_menu() {
|
|
219
|
+
add_options_page(
|
|
220
|
+
__('Site Settings Manager', 'site-settings-manager'),
|
|
221
|
+
__('Site Settings', 'site-settings-manager'),
|
|
222
|
+
'manage_options',
|
|
223
|
+
self::PAGE_SLUG,
|
|
224
|
+
array(__CLASS__, 'render_settings_page')
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Register settings
|
|
230
|
+
*/
|
|
231
|
+
public static function register_settings() {
|
|
232
|
+
// Register settings
|
|
233
|
+
register_setting(
|
|
234
|
+
self::OPTION_GROUP,
|
|
235
|
+
'ssm_site_title',
|
|
236
|
+
array(
|
|
237
|
+
'type' => 'string',
|
|
238
|
+
'sanitize_callback' => 'sanitize_text_field',
|
|
239
|
+
'default' => '',
|
|
240
|
+
)
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
register_setting(
|
|
244
|
+
self::OPTION_GROUP,
|
|
245
|
+
'ssm_site_description',
|
|
246
|
+
array(
|
|
247
|
+
'type' => 'string',
|
|
248
|
+
'sanitize_callback' => 'sanitize_textarea_field',
|
|
249
|
+
'default' => '',
|
|
250
|
+
)
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
register_setting(
|
|
254
|
+
self::OPTION_GROUP,
|
|
255
|
+
'ssm_enable_feature',
|
|
256
|
+
array(
|
|
257
|
+
'type' => 'boolean',
|
|
258
|
+
'sanitize_callback' => array(__CLASS__, 'sanitize_checkbox'),
|
|
259
|
+
'default' => false,
|
|
260
|
+
)
|
|
261
|
+
);
|
|
262
|
+
|
|
263
|
+
register_setting(
|
|
264
|
+
self::OPTION_GROUP,
|
|
265
|
+
'ssm_api_key',
|
|
266
|
+
array(
|
|
267
|
+
'type' => 'string',
|
|
268
|
+
'sanitize_callback' => array(__CLASS__, 'sanitize_api_key'),
|
|
269
|
+
'default' => '',
|
|
270
|
+
)
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
register_setting(
|
|
274
|
+
self::OPTION_GROUP,
|
|
275
|
+
'ssm_items_per_page',
|
|
276
|
+
array(
|
|
277
|
+
'type' => 'integer',
|
|
278
|
+
'sanitize_callback' => array(__CLASS__, 'sanitize_items_per_page'),
|
|
279
|
+
'default' => 10,
|
|
280
|
+
)
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
register_setting(
|
|
284
|
+
self::OPTION_GROUP,
|
|
285
|
+
'ssm_theme_color',
|
|
286
|
+
array(
|
|
287
|
+
'type' => 'string',
|
|
288
|
+
'sanitize_callback' => 'sanitize_hex_color',
|
|
289
|
+
'default' => '#0073aa',
|
|
290
|
+
)
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
register_setting(
|
|
294
|
+
self::OPTION_GROUP,
|
|
295
|
+
'ssm_email_notifications',
|
|
296
|
+
array(
|
|
297
|
+
'type' => 'string',
|
|
298
|
+
'sanitize_callback' => array(__CLASS__, 'sanitize_email_list'),
|
|
299
|
+
'default' => '',
|
|
300
|
+
)
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
// Add settings sections
|
|
304
|
+
add_settings_section(
|
|
305
|
+
'ssm_general_section',
|
|
306
|
+
__('General Settings', 'site-settings-manager'),
|
|
307
|
+
array(__CLASS__, 'render_general_section'),
|
|
308
|
+
self::PAGE_SLUG
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
add_settings_section(
|
|
312
|
+
'ssm_api_section',
|
|
313
|
+
__('API Settings', 'site-settings-manager'),
|
|
314
|
+
array(__CLASS__, 'render_api_section'),
|
|
315
|
+
self::PAGE_SLUG
|
|
316
|
+
);
|
|
317
|
+
|
|
318
|
+
add_settings_section(
|
|
319
|
+
'ssm_display_section',
|
|
320
|
+
__('Display Settings', 'site-settings-manager'),
|
|
321
|
+
array(__CLASS__, 'render_display_section'),
|
|
322
|
+
self::PAGE_SLUG
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
// Add settings fields - General Section
|
|
326
|
+
add_settings_field(
|
|
327
|
+
'ssm_site_title',
|
|
328
|
+
__('Site Title', 'site-settings-manager'),
|
|
329
|
+
array('SSM_Settings_Fields', 'render_text_field'),
|
|
330
|
+
self::PAGE_SLUG,
|
|
331
|
+
'ssm_general_section',
|
|
332
|
+
array(
|
|
333
|
+
'label_for' => 'ssm_site_title',
|
|
334
|
+
'option_name' => 'ssm_site_title',
|
|
335
|
+
'description' => __('Enter your site title', 'site-settings-manager'),
|
|
336
|
+
)
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
add_settings_field(
|
|
340
|
+
'ssm_site_description',
|
|
341
|
+
__('Site Description', 'site-settings-manager'),
|
|
342
|
+
array('SSM_Settings_Fields', 'render_textarea_field'),
|
|
343
|
+
self::PAGE_SLUG,
|
|
344
|
+
'ssm_general_section',
|
|
345
|
+
array(
|
|
346
|
+
'label_for' => 'ssm_site_description',
|
|
347
|
+
'option_name' => 'ssm_site_description',
|
|
348
|
+
'description' => __('Enter your site description', 'site-settings-manager'),
|
|
349
|
+
'rows' => 4,
|
|
350
|
+
)
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
add_settings_field(
|
|
354
|
+
'ssm_enable_feature',
|
|
355
|
+
__('Enable Feature', 'site-settings-manager'),
|
|
356
|
+
array('SSM_Settings_Fields', 'render_checkbox_field'),
|
|
357
|
+
self::PAGE_SLUG,
|
|
358
|
+
'ssm_general_section',
|
|
359
|
+
array(
|
|
360
|
+
'label_for' => 'ssm_enable_feature',
|
|
361
|
+
'option_name' => 'ssm_enable_feature',
|
|
362
|
+
'description' => __('Enable this feature', 'site-settings-manager'),
|
|
363
|
+
)
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
// Add settings fields - API Section
|
|
367
|
+
add_settings_field(
|
|
368
|
+
'ssm_api_key',
|
|
369
|
+
__('API Key', 'site-settings-manager'),
|
|
370
|
+
array('SSM_Settings_Fields', 'render_password_field'),
|
|
371
|
+
self::PAGE_SLUG,
|
|
372
|
+
'ssm_api_section',
|
|
373
|
+
array(
|
|
374
|
+
'label_for' => 'ssm_api_key',
|
|
375
|
+
'option_name' => 'ssm_api_key',
|
|
376
|
+
'description' => __('Enter your API key', 'site-settings-manager'),
|
|
377
|
+
)
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
add_settings_field(
|
|
381
|
+
'ssm_email_notifications',
|
|
382
|
+
__('Email Notifications', 'site-settings-manager'),
|
|
383
|
+
array('SSM_Settings_Fields', 'render_text_field'),
|
|
384
|
+
self::PAGE_SLUG,
|
|
385
|
+
'ssm_api_section',
|
|
386
|
+
array(
|
|
387
|
+
'label_for' => 'ssm_email_notifications',
|
|
388
|
+
'option_name' => 'ssm_email_notifications',
|
|
389
|
+
'description' => __('Comma-separated email addresses', 'site-settings-manager'),
|
|
390
|
+
)
|
|
391
|
+
);
|
|
392
|
+
|
|
393
|
+
// Add settings fields - Display Section
|
|
394
|
+
add_settings_field(
|
|
395
|
+
'ssm_items_per_page',
|
|
396
|
+
__('Items Per Page', 'site-settings-manager'),
|
|
397
|
+
array('SSM_Settings_Fields', 'render_number_field'),
|
|
398
|
+
self::PAGE_SLUG,
|
|
399
|
+
'ssm_display_section',
|
|
400
|
+
array(
|
|
401
|
+
'label_for' => 'ssm_items_per_page',
|
|
402
|
+
'option_name' => 'ssm_items_per_page',
|
|
403
|
+
'description' => __('Number of items to display per page', 'site-settings-manager'),
|
|
404
|
+
'min' => 1,
|
|
405
|
+
'max' => 100,
|
|
406
|
+
)
|
|
407
|
+
);
|
|
408
|
+
|
|
409
|
+
add_settings_field(
|
|
410
|
+
'ssm_theme_color',
|
|
411
|
+
__('Theme Color', 'site-settings-manager'),
|
|
412
|
+
array('SSM_Settings_Fields', 'render_color_field'),
|
|
413
|
+
self::PAGE_SLUG,
|
|
414
|
+
'ssm_display_section',
|
|
415
|
+
array(
|
|
416
|
+
'label_for' => 'ssm_theme_color',
|
|
417
|
+
'option_name' => 'ssm_theme_color',
|
|
418
|
+
'description' => __('Choose your theme color', 'site-settings-manager'),
|
|
419
|
+
)
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Render general section
|
|
425
|
+
*/
|
|
426
|
+
public static function render_general_section() {
|
|
427
|
+
echo '<p>' . esc_html__('Configure general site settings.', 'site-settings-manager') . '</p>';
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Render API section
|
|
432
|
+
*/
|
|
433
|
+
public static function render_api_section() {
|
|
434
|
+
echo '<p>' . esc_html__('Configure API and integration settings.', 'site-settings-manager') . '</p>';
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Render display section
|
|
439
|
+
*/
|
|
440
|
+
public static function render_display_section() {
|
|
441
|
+
echo '<p>' . esc_html__('Configure display and appearance settings.', 'site-settings-manager') . '</p>';
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Sanitize checkbox
|
|
446
|
+
*/
|
|
447
|
+
public static function sanitize_checkbox($value) {
|
|
448
|
+
return $value ? true : false;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Sanitize API key
|
|
453
|
+
*/
|
|
454
|
+
public static function sanitize_api_key($value) {
|
|
455
|
+
$value = sanitize_text_field($value);
|
|
456
|
+
|
|
457
|
+
// Validate API key format (example: alphanumeric, 32 characters)
|
|
458
|
+
if (!empty($value) && !preg_match('/^[a-zA-Z0-9]{32}$/', $value)) {
|
|
459
|
+
add_settings_error(
|
|
460
|
+
'ssm_api_key',
|
|
461
|
+
'invalid_api_key',
|
|
462
|
+
__('API key must be 32 alphanumeric characters.', 'site-settings-manager'),
|
|
463
|
+
'error'
|
|
464
|
+
);
|
|
465
|
+
return get_option('ssm_api_key'); // Return old value
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return $value;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Sanitize items per page
|
|
473
|
+
*/
|
|
474
|
+
public static function sanitize_items_per_page($value) {
|
|
475
|
+
$value = intval($value);
|
|
476
|
+
|
|
477
|
+
if ($value < 1 || $value > 100) {
|
|
478
|
+
add_settings_error(
|
|
479
|
+
'ssm_items_per_page',
|
|
480
|
+
'invalid_items_per_page',
|
|
481
|
+
__('Items per page must be between 1 and 100.', 'site-settings-manager'),
|
|
482
|
+
'error'
|
|
483
|
+
);
|
|
484
|
+
return get_option('ssm_items_per_page'); // Return old value
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
return $value;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Sanitize email list
|
|
492
|
+
*/
|
|
493
|
+
public static function sanitize_email_list($value) {
|
|
494
|
+
$emails = array_map('trim', explode(',', $value));
|
|
495
|
+
$valid_emails = array();
|
|
496
|
+
|
|
497
|
+
foreach ($emails as $email) {
|
|
498
|
+
if (is_email($email)) {
|
|
499
|
+
$valid_emails[] = $email;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (count($emails) !== count($valid_emails)) {
|
|
504
|
+
add_settings_error(
|
|
505
|
+
'ssm_email_notifications',
|
|
506
|
+
'invalid_emails',
|
|
507
|
+
__('Some email addresses are invalid and were removed.', 'site-settings-manager'),
|
|
508
|
+
'warning'
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
return implode(', ', $valid_emails);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Render settings page
|
|
517
|
+
*/
|
|
518
|
+
public static function render_settings_page() {
|
|
519
|
+
// Check user capabilities
|
|
520
|
+
if (!current_user_can('manage_options')) {
|
|
521
|
+
wp_die(__('You do not have sufficient permissions to access this page.', 'site-settings-manager'));
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Include the view
|
|
525
|
+
include SSM_PLUGIN_DIR . 'admin/views/settings-page.php';
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
## Settings Fields Class
|
|
533
|
+
|
|
534
|
+
### File: `includes/class-settings-fields.php`
|
|
535
|
+
|
|
536
|
+
```php
|
|
537
|
+
<?php
|
|
538
|
+
/**
|
|
539
|
+
* Settings fields rendering
|
|
540
|
+
*
|
|
541
|
+
* @package Site_Settings_Manager
|
|
542
|
+
*/
|
|
543
|
+
|
|
544
|
+
class SSM_Settings_Fields {
|
|
545
|
+
/**
|
|
546
|
+
* Render text field
|
|
547
|
+
*/
|
|
548
|
+
public static function render_text_field($args) {
|
|
549
|
+
$option_name = $args['option_name'];
|
|
550
|
+
$value = get_option($option_name, '');
|
|
551
|
+
$description = isset($args['description']) ? $args['description'] : '';
|
|
552
|
+
|
|
553
|
+
printf(
|
|
554
|
+
'<input type="text" id="%s" name="%s" value="%s" class="regular-text">',
|
|
555
|
+
esc_attr($args['label_for']),
|
|
556
|
+
esc_attr($option_name),
|
|
557
|
+
esc_attr($value)
|
|
558
|
+
);
|
|
559
|
+
|
|
560
|
+
if ($description) {
|
|
561
|
+
printf('<p class="description">%s</p>', esc_html($description));
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Render textarea field
|
|
567
|
+
*/
|
|
568
|
+
public static function render_textarea_field($args) {
|
|
569
|
+
$option_name = $args['option_name'];
|
|
570
|
+
$value = get_option($option_name, '');
|
|
571
|
+
$description = isset($args['description']) ? $args['description'] : '';
|
|
572
|
+
$rows = isset($args['rows']) ? intval($args['rows']) : 5;
|
|
573
|
+
|
|
574
|
+
printf(
|
|
575
|
+
'<textarea id="%s" name="%s" rows="%d" class="large-text">%s</textarea>',
|
|
576
|
+
esc_attr($args['label_for']),
|
|
577
|
+
esc_attr($option_name),
|
|
578
|
+
$rows,
|
|
579
|
+
esc_textarea($value)
|
|
580
|
+
);
|
|
581
|
+
|
|
582
|
+
if ($description) {
|
|
583
|
+
printf('<p class="description">%s</p>', esc_html($description));
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/**
|
|
588
|
+
* Render checkbox field
|
|
589
|
+
*/
|
|
590
|
+
public static function render_checkbox_field($args) {
|
|
591
|
+
$option_name = $args['option_name'];
|
|
592
|
+
$value = get_option($option_name, false);
|
|
593
|
+
$description = isset($args['description']) ? $args['description'] : '';
|
|
594
|
+
|
|
595
|
+
printf(
|
|
596
|
+
'<label><input type="checkbox" id="%s" name="%s" value="1" %s> %s</label>',
|
|
597
|
+
esc_attr($args['label_for']),
|
|
598
|
+
esc_attr($option_name),
|
|
599
|
+
checked($value, true, false),
|
|
600
|
+
esc_html($description)
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Render password field
|
|
606
|
+
*/
|
|
607
|
+
public static function render_password_field($args) {
|
|
608
|
+
$option_name = $args['option_name'];
|
|
609
|
+
$value = get_option($option_name, '');
|
|
610
|
+
$description = isset($args['description']) ? $args['description'] : '';
|
|
611
|
+
|
|
612
|
+
printf(
|
|
613
|
+
'<input type="password" id="%s" name="%s" value="%s" class="regular-text">',
|
|
614
|
+
esc_attr($args['label_for']),
|
|
615
|
+
esc_attr($option_name),
|
|
616
|
+
esc_attr($value)
|
|
617
|
+
);
|
|
618
|
+
|
|
619
|
+
if ($description) {
|
|
620
|
+
printf('<p class="description">%s</p>', esc_html($description));
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Render number field
|
|
626
|
+
*/
|
|
627
|
+
public static function render_number_field($args) {
|
|
628
|
+
$option_name = $args['option_name'];
|
|
629
|
+
$value = get_option($option_name, '');
|
|
630
|
+
$description = isset($args['description']) ? $args['description'] : '';
|
|
631
|
+
$min = isset($args['min']) ? intval($args['min']) : '';
|
|
632
|
+
$max = isset($args['max']) ? intval($args['max']) : '';
|
|
633
|
+
|
|
634
|
+
printf(
|
|
635
|
+
'<input type="number" id="%s" name="%s" value="%s" min="%s" max="%s" class="small-text">',
|
|
636
|
+
esc_attr($args['label_for']),
|
|
637
|
+
esc_attr($option_name),
|
|
638
|
+
esc_attr($value),
|
|
639
|
+
esc_attr($min),
|
|
640
|
+
esc_attr($max)
|
|
641
|
+
);
|
|
642
|
+
|
|
643
|
+
if ($description) {
|
|
644
|
+
printf('<p class="description">%s</p>', esc_html($description));
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Render color field
|
|
650
|
+
*/
|
|
651
|
+
public static function render_color_field($args) {
|
|
652
|
+
$option_name = $args['option_name'];
|
|
653
|
+
$value = get_option($option_name, '#0073aa');
|
|
654
|
+
$description = isset($args['description']) ? $args['description'] : '';
|
|
655
|
+
|
|
656
|
+
printf(
|
|
657
|
+
'<input type="text" id="%s" name="%s" value="%s" class="ssm-color-picker">',
|
|
658
|
+
esc_attr($args['label_for']),
|
|
659
|
+
esc_attr($option_name),
|
|
660
|
+
esc_attr($value)
|
|
661
|
+
);
|
|
662
|
+
|
|
663
|
+
if ($description) {
|
|
664
|
+
printf('<p class="description">%s</p>', esc_html($description));
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* Render select field
|
|
670
|
+
*/
|
|
671
|
+
public static function render_select_field($args) {
|
|
672
|
+
$option_name = $args['option_name'];
|
|
673
|
+
$value = get_option($option_name, '');
|
|
674
|
+
$description = isset($args['description']) ? $args['description'] : '';
|
|
675
|
+
$options = isset($args['options']) ? $args['options'] : array();
|
|
676
|
+
|
|
677
|
+
printf('<select id="%s" name="%s">', esc_attr($args['label_for']), esc_attr($option_name));
|
|
678
|
+
|
|
679
|
+
foreach ($options as $option_value => $option_label) {
|
|
680
|
+
printf(
|
|
681
|
+
'<option value="%s" %s>%s</option>',
|
|
682
|
+
esc_attr($option_value),
|
|
683
|
+
selected($value, $option_value, false),
|
|
684
|
+
esc_html($option_label)
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
echo '</select>';
|
|
689
|
+
|
|
690
|
+
if ($description) {
|
|
691
|
+
printf('<p class="description">%s</p>', esc_html($description));
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* Render radio field
|
|
697
|
+
*/
|
|
698
|
+
public static function render_radio_field($args) {
|
|
699
|
+
$option_name = $args['option_name'];
|
|
700
|
+
$value = get_option($option_name, '');
|
|
701
|
+
$description = isset($args['description']) ? $args['description'] : '';
|
|
702
|
+
$options = isset($args['options']) ? $args['options'] : array();
|
|
703
|
+
|
|
704
|
+
foreach ($options as $option_value => $option_label) {
|
|
705
|
+
printf(
|
|
706
|
+
'<label><input type="radio" name="%s" value="%s" %s> %s</label><br>',
|
|
707
|
+
esc_attr($option_name),
|
|
708
|
+
esc_attr($option_value),
|
|
709
|
+
checked($value, $option_value, false),
|
|
710
|
+
esc_html($option_label)
|
|
711
|
+
);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
if ($description) {
|
|
715
|
+
printf('<p class="description">%s</p>', esc_html($description));
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
---
|
|
722
|
+
|
|
723
|
+
## View Files
|
|
724
|
+
|
|
725
|
+
### File: `admin/views/settings-page.php`
|
|
726
|
+
|
|
727
|
+
```php
|
|
728
|
+
<?php
|
|
729
|
+
/**
|
|
730
|
+
* Settings page view
|
|
731
|
+
*
|
|
732
|
+
* @package Site_Settings_Manager
|
|
733
|
+
*/
|
|
734
|
+
|
|
735
|
+
// Exit if accessed directly
|
|
736
|
+
if (!defined('ABSPATH')) {
|
|
737
|
+
exit;
|
|
738
|
+
}
|
|
739
|
+
?>
|
|
740
|
+
|
|
741
|
+
<div class="wrap ssm-settings-wrap">
|
|
742
|
+
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
|
|
743
|
+
|
|
744
|
+
<?php settings_errors(); ?>
|
|
745
|
+
|
|
746
|
+
<div class="ssm-settings-container">
|
|
747
|
+
<div class="ssm-settings-main">
|
|
748
|
+
<form method="post" action="options.php">
|
|
749
|
+
<?php
|
|
750
|
+
settings_fields(SSM_Settings_Page::OPTION_GROUP);
|
|
751
|
+
do_settings_sections(SSM_Settings_Page::PAGE_SLUG);
|
|
752
|
+
submit_button(__('Save Settings', 'site-settings-manager'));
|
|
753
|
+
?>
|
|
754
|
+
</form>
|
|
755
|
+
</div>
|
|
756
|
+
|
|
757
|
+
<div class="ssm-settings-sidebar">
|
|
758
|
+
<?php include SSM_PLUGIN_DIR . 'admin/views/settings-sidebar.php'; ?>
|
|
759
|
+
</div>
|
|
760
|
+
</div>
|
|
761
|
+
</div>
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
### File: `admin/views/settings-sidebar.php`
|
|
765
|
+
|
|
766
|
+
```php
|
|
767
|
+
<?php
|
|
768
|
+
/**
|
|
769
|
+
* Settings sidebar view
|
|
770
|
+
*
|
|
771
|
+
* @package Site_Settings_Manager
|
|
772
|
+
*/
|
|
773
|
+
|
|
774
|
+
// Exit if accessed directly
|
|
775
|
+
if (!defined('ABSPATH')) {
|
|
776
|
+
exit;
|
|
777
|
+
}
|
|
778
|
+
?>
|
|
779
|
+
|
|
780
|
+
<div class="ssm-sidebar-box">
|
|
781
|
+
<h3><?php _e('About This Plugin', 'site-settings-manager'); ?></h3>
|
|
782
|
+
<p><?php _e('Site Settings Manager provides a comprehensive settings interface for your WordPress site.', 'site-settings-manager'); ?></p>
|
|
783
|
+
</div>
|
|
784
|
+
|
|
785
|
+
<div class="ssm-sidebar-box">
|
|
786
|
+
<h3><?php _e('Documentation', 'site-settings-manager'); ?></h3>
|
|
787
|
+
<ul>
|
|
788
|
+
<li><a href="#" target="_blank"><?php _e('Getting Started', 'site-settings-manager'); ?></a></li>
|
|
789
|
+
<li><a href="#" target="_blank"><?php _e('API Documentation', 'site-settings-manager'); ?></a></li>
|
|
790
|
+
<li><a href="#" target="_blank"><?php _e('Support Forum', 'site-settings-manager'); ?></a></li>
|
|
791
|
+
</ul>
|
|
792
|
+
</div>
|
|
793
|
+
|
|
794
|
+
<div class="ssm-sidebar-box">
|
|
795
|
+
<h3><?php _e('System Info', 'site-settings-manager'); ?></h3>
|
|
796
|
+
<table class="ssm-info-table">
|
|
797
|
+
<tr>
|
|
798
|
+
<td><?php _e('Plugin Version:', 'site-settings-manager'); ?></td>
|
|
799
|
+
<td><?php echo esc_html(SSM_VERSION); ?></td>
|
|
800
|
+
</tr>
|
|
801
|
+
<tr>
|
|
802
|
+
<td><?php _e('WordPress Version:', 'site-settings-manager'); ?></td>
|
|
803
|
+
<td><?php echo esc_html(get_bloginfo('version')); ?></td>
|
|
804
|
+
</tr>
|
|
805
|
+
<tr>
|
|
806
|
+
<td><?php _e('PHP Version:', 'site-settings-manager'); ?></td>
|
|
807
|
+
<td><?php echo esc_html(PHP_VERSION); ?></td>
|
|
808
|
+
</tr>
|
|
809
|
+
</table>
|
|
810
|
+
</div>
|
|
811
|
+
|
|
812
|
+
<div class="ssm-sidebar-box ssm-support-box">
|
|
813
|
+
<h3><?php _e('Need Help?', 'site-settings-manager'); ?></h3>
|
|
814
|
+
<p><?php _e('If you need assistance, please visit our support forum.', 'site-settings-manager'); ?></p>
|
|
815
|
+
<a href="#" class="button button-primary" target="_blank">
|
|
816
|
+
<?php _e('Get Support', 'site-settings-manager'); ?>
|
|
817
|
+
</a>
|
|
818
|
+
</div>
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
---
|
|
822
|
+
|
|
823
|
+
## Assets
|
|
824
|
+
|
|
825
|
+
### File: `admin/css/admin.css`
|
|
826
|
+
|
|
827
|
+
```css
|
|
828
|
+
/* Settings Page Layout */
|
|
829
|
+
.ssm-settings-wrap {
|
|
830
|
+
margin: 20px 20px 0 0;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
.ssm-settings-container {
|
|
834
|
+
display: flex;
|
|
835
|
+
gap: 30px;
|
|
836
|
+
margin-top: 20px;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
.ssm-settings-main {
|
|
840
|
+
flex: 1;
|
|
841
|
+
background: #fff;
|
|
842
|
+
padding: 20px;
|
|
843
|
+
border: 1px solid #ccd0d4;
|
|
844
|
+
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
.ssm-settings-sidebar {
|
|
848
|
+
width: 300px;
|
|
849
|
+
flex-shrink: 0;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
@media (max-width: 1024px) {
|
|
853
|
+
.ssm-settings-container {
|
|
854
|
+
flex-direction: column;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
.ssm-settings-sidebar {
|
|
858
|
+
width: 100%;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
/* Settings Sections */
|
|
863
|
+
.ssm-settings-main h2 {
|
|
864
|
+
margin-top: 0;
|
|
865
|
+
padding-bottom: 10px;
|
|
866
|
+
border-bottom: 1px solid #e0e0e0;
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
.ssm-settings-main .form-table {
|
|
870
|
+
margin-top: 20px;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
.ssm-settings-main .form-table th {
|
|
874
|
+
padding: 15px 10px 15px 0;
|
|
875
|
+
width: 200px;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
.ssm-settings-main .form-table td {
|
|
879
|
+
padding: 15px 10px;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/* Sidebar Boxes */
|
|
883
|
+
.ssm-sidebar-box {
|
|
884
|
+
background: #fff;
|
|
885
|
+
padding: 20px;
|
|
886
|
+
margin-bottom: 20px;
|
|
887
|
+
border: 1px solid #ccd0d4;
|
|
888
|
+
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
.ssm-sidebar-box h3 {
|
|
892
|
+
margin-top: 0;
|
|
893
|
+
margin-bottom: 15px;
|
|
894
|
+
font-size: 14px;
|
|
895
|
+
font-weight: 600;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
.ssm-sidebar-box p {
|
|
899
|
+
margin: 0 0 15px;
|
|
900
|
+
font-size: 13px;
|
|
901
|
+
line-height: 1.6;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
.ssm-sidebar-box ul {
|
|
905
|
+
margin: 0;
|
|
906
|
+
padding: 0;
|
|
907
|
+
list-style: none;
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
.ssm-sidebar-box ul li {
|
|
911
|
+
margin-bottom: 8px;
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
.ssm-sidebar-box ul li a {
|
|
915
|
+
text-decoration: none;
|
|
916
|
+
font-size: 13px;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
.ssm-sidebar-box ul li a:hover {
|
|
920
|
+
text-decoration: underline;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
/* Info Table */
|
|
924
|
+
.ssm-info-table {
|
|
925
|
+
width: 100%;
|
|
926
|
+
font-size: 13px;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
.ssm-info-table tr {
|
|
930
|
+
border-bottom: 1px solid #f0f0f0;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
.ssm-info-table tr:last-child {
|
|
934
|
+
border-bottom: none;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
.ssm-info-table td {
|
|
938
|
+
padding: 8px 0;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
.ssm-info-table td:first-child {
|
|
942
|
+
font-weight: 600;
|
|
943
|
+
width: 50%;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
/* Support Box */
|
|
947
|
+
.ssm-support-box {
|
|
948
|
+
background: #f7f7f7;
|
|
949
|
+
border-left: 4px solid #0073aa;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
.ssm-support-box .button {
|
|
953
|
+
width: 100%;
|
|
954
|
+
text-align: center;
|
|
955
|
+
margin-top: 10px;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/* Color Picker */
|
|
959
|
+
.ssm-color-picker {
|
|
960
|
+
max-width: 100px;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
/* Success/Error Messages */
|
|
964
|
+
.ssm-settings-wrap .notice {
|
|
965
|
+
margin: 20px 0;
|
|
966
|
+
}
|
|
967
|
+
```
|
|
968
|
+
|
|
969
|
+
### File: `admin/js/admin.js`
|
|
970
|
+
|
|
971
|
+
```javascript
|
|
972
|
+
(function($) {
|
|
973
|
+
'use strict';
|
|
974
|
+
|
|
975
|
+
$(document).ready(function() {
|
|
976
|
+
// Initialize color picker
|
|
977
|
+
if (typeof $.fn.wpColorPicker !== 'undefined') {
|
|
978
|
+
$('.ssm-color-picker').wpColorPicker();
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
// Form validation
|
|
982
|
+
$('form').on('submit', function(e) {
|
|
983
|
+
var isValid = true;
|
|
984
|
+
|
|
985
|
+
// Validate API key if present
|
|
986
|
+
var apiKey = $('#ssm_api_key').val();
|
|
987
|
+
if (apiKey && !/^[a-zA-Z0-9]{32}$/.test(apiKey)) {
|
|
988
|
+
alert('API key must be 32 alphanumeric characters.');
|
|
989
|
+
isValid = false;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
// Validate items per page
|
|
993
|
+
var itemsPerPage = parseInt($('#ssm_items_per_page').val());
|
|
994
|
+
if (itemsPerPage < 1 || itemsPerPage > 100) {
|
|
995
|
+
alert('Items per page must be between 1 and 100.');
|
|
996
|
+
isValid = false;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
if (!isValid) {
|
|
1000
|
+
e.preventDefault();
|
|
1001
|
+
}
|
|
1002
|
+
});
|
|
1003
|
+
|
|
1004
|
+
// Show/hide conditional fields
|
|
1005
|
+
$('#ssm_enable_feature').on('change', function() {
|
|
1006
|
+
if ($(this).is(':checked')) {
|
|
1007
|
+
$('.conditional-field').slideDown();
|
|
1008
|
+
} else {
|
|
1009
|
+
$('.conditional-field').slideUp();
|
|
1010
|
+
}
|
|
1011
|
+
}).trigger('change');
|
|
1012
|
+
});
|
|
1013
|
+
|
|
1014
|
+
})(jQuery);
|
|
1015
|
+
```
|
|
1016
|
+
|
|
1017
|
+
---
|
|
1018
|
+
|
|
1019
|
+
## Uninstall
|
|
1020
|
+
|
|
1021
|
+
### File: `uninstall.php`
|
|
1022
|
+
|
|
1023
|
+
```php
|
|
1024
|
+
<?php
|
|
1025
|
+
/**
|
|
1026
|
+
* Uninstall script
|
|
1027
|
+
*
|
|
1028
|
+
* @package Site_Settings_Manager
|
|
1029
|
+
*/
|
|
1030
|
+
|
|
1031
|
+
// Exit if accessed directly or not uninstalling
|
|
1032
|
+
if (!defined('WP_UNINSTALL_PLUGIN')) {
|
|
1033
|
+
exit;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
// Delete all plugin options
|
|
1037
|
+
$options = array(
|
|
1038
|
+
'ssm_site_title',
|
|
1039
|
+
'ssm_site_description',
|
|
1040
|
+
'ssm_enable_feature',
|
|
1041
|
+
'ssm_api_key',
|
|
1042
|
+
'ssm_items_per_page',
|
|
1043
|
+
'ssm_theme_color',
|
|
1044
|
+
'ssm_email_notifications',
|
|
1045
|
+
);
|
|
1046
|
+
|
|
1047
|
+
foreach ($options as $option) {
|
|
1048
|
+
delete_option($option);
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
// Clear any cached data
|
|
1052
|
+
wp_cache_flush();
|
|
1053
|
+
```
|
|
1054
|
+
|
|
1055
|
+
---
|
|
1056
|
+
|
|
1057
|
+
## Usage Examples
|
|
1058
|
+
|
|
1059
|
+
### Accessing Settings in Your Code
|
|
1060
|
+
|
|
1061
|
+
```php
|
|
1062
|
+
<?php
|
|
1063
|
+
// Get individual settings
|
|
1064
|
+
$site_title = get_option('ssm_site_title', '');
|
|
1065
|
+
$enable_feature = get_option('ssm_enable_feature', false);
|
|
1066
|
+
$items_per_page = get_option('ssm_items_per_page', 10);
|
|
1067
|
+
$theme_color = get_option('ssm_theme_color', '#0073aa');
|
|
1068
|
+
|
|
1069
|
+
// Use settings
|
|
1070
|
+
if ($enable_feature) {
|
|
1071
|
+
// Feature is enabled
|
|
1072
|
+
echo '<h1>' . esc_html($site_title) . '</h1>';
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
// Use in queries
|
|
1076
|
+
$args = array(
|
|
1077
|
+
'posts_per_page' => $items_per_page,
|
|
1078
|
+
);
|
|
1079
|
+
$query = new WP_Query($args);
|
|
1080
|
+
?>
|
|
1081
|
+
```
|
|
1082
|
+
|
|
1083
|
+
### Programmatically Update Settings
|
|
1084
|
+
|
|
1085
|
+
```php
|
|
1086
|
+
<?php
|
|
1087
|
+
// Update settings
|
|
1088
|
+
update_option('ssm_site_title', 'New Site Title');
|
|
1089
|
+
update_option('ssm_enable_feature', true);
|
|
1090
|
+
update_option('ssm_items_per_page', 20);
|
|
1091
|
+
|
|
1092
|
+
// Get and modify
|
|
1093
|
+
$emails = get_option('ssm_email_notifications', '');
|
|
1094
|
+
$email_array = array_map('trim', explode(',', $emails));
|
|
1095
|
+
$email_array[] = 'new@example.com';
|
|
1096
|
+
update_option('ssm_email_notifications', implode(', ', $email_array));
|
|
1097
|
+
?>
|
|
1098
|
+
```
|
|
1099
|
+
|
|
1100
|
+
### Add Custom Validation
|
|
1101
|
+
|
|
1102
|
+
```php
|
|
1103
|
+
<?php
|
|
1104
|
+
// Add to class-settings-page.php
|
|
1105
|
+
public static function sanitize_custom_field($value) {
|
|
1106
|
+
$value = sanitize_text_field($value);
|
|
1107
|
+
|
|
1108
|
+
// Custom validation logic
|
|
1109
|
+
if (strlen($value) < 5) {
|
|
1110
|
+
add_settings_error(
|
|
1111
|
+
'ssm_custom_field',
|
|
1112
|
+
'too_short',
|
|
1113
|
+
__('Value must be at least 5 characters.', 'site-settings-manager'),
|
|
1114
|
+
'error'
|
|
1115
|
+
);
|
|
1116
|
+
return get_option('ssm_custom_field');
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
return $value;
|
|
1120
|
+
}
|
|
1121
|
+
?>
|
|
1122
|
+
```
|
|
1123
|
+
|
|
1124
|
+
### Add New Settings Section
|
|
1125
|
+
|
|
1126
|
+
```php
|
|
1127
|
+
<?php
|
|
1128
|
+
// In register_settings() method
|
|
1129
|
+
add_settings_section(
|
|
1130
|
+
'ssm_custom_section',
|
|
1131
|
+
__('Custom Settings', 'site-settings-manager'),
|
|
1132
|
+
array(__CLASS__, 'render_custom_section'),
|
|
1133
|
+
self::PAGE_SLUG
|
|
1134
|
+
);
|
|
1135
|
+
|
|
1136
|
+
add_settings_field(
|
|
1137
|
+
'ssm_custom_field',
|
|
1138
|
+
__('Custom Field', 'site-settings-manager'),
|
|
1139
|
+
array('SSM_Settings_Fields', 'render_text_field'),
|
|
1140
|
+
self::PAGE_SLUG,
|
|
1141
|
+
'ssm_custom_section',
|
|
1142
|
+
array(
|
|
1143
|
+
'label_for' => 'ssm_custom_field',
|
|
1144
|
+
'option_name' => 'ssm_custom_field',
|
|
1145
|
+
'description' => __('Enter custom value', 'site-settings-manager'),
|
|
1146
|
+
)
|
|
1147
|
+
);
|
|
1148
|
+
?>
|
|
1149
|
+
```
|
|
1150
|
+
|
|
1151
|
+
---
|
|
1152
|
+
|
|
1153
|
+
## Key Features
|
|
1154
|
+
|
|
1155
|
+
### 1. Settings API Integration
|
|
1156
|
+
- **Proper registration** with `register_setting()`
|
|
1157
|
+
- **Sections and fields** with `add_settings_section()` and `add_settings_field()`
|
|
1158
|
+
- **Automatic form handling** with `settings_fields()` and `do_settings_sections()`
|
|
1159
|
+
- **Built-in validation** and error handling
|
|
1160
|
+
|
|
1161
|
+
### 2. Field Types
|
|
1162
|
+
- **Text field**: Single-line text input
|
|
1163
|
+
- **Textarea field**: Multi-line text input
|
|
1164
|
+
- **Checkbox field**: Boolean toggle
|
|
1165
|
+
- **Password field**: Masked input
|
|
1166
|
+
- **Number field**: Numeric input with min/max
|
|
1167
|
+
- **Color field**: Color picker integration
|
|
1168
|
+
- **Select field**: Dropdown selection
|
|
1169
|
+
- **Radio field**: Radio button group
|
|
1170
|
+
|
|
1171
|
+
### 3. Validation & Sanitization
|
|
1172
|
+
- **Built-in sanitization**: `sanitize_text_field()`, `sanitize_textarea_field()`, `sanitize_hex_color()`
|
|
1173
|
+
- **Custom validation**: API key format, email list, numeric ranges
|
|
1174
|
+
- **Error messages**: `add_settings_error()` for user feedback
|
|
1175
|
+
- **Fallback values**: Return old value on validation failure
|
|
1176
|
+
|
|
1177
|
+
### 4. Security
|
|
1178
|
+
- **Capability checks**: `current_user_can('manage_options')`
|
|
1179
|
+
- **Nonce verification**: Automatic with Settings API
|
|
1180
|
+
- **Input sanitization**: All inputs sanitized
|
|
1181
|
+
- **Output escaping**: All outputs escaped
|
|
1182
|
+
|
|
1183
|
+
### 5. User Experience
|
|
1184
|
+
- **Clean layout**: Two-column design with sidebar
|
|
1185
|
+
- **Helpful descriptions**: Field-level help text
|
|
1186
|
+
- **System information**: Plugin and environment details
|
|
1187
|
+
- **Color picker**: WordPress color picker integration
|
|
1188
|
+
- **Responsive design**: Mobile-friendly layout
|
|
1189
|
+
|
|
1190
|
+
---
|
|
1191
|
+
|
|
1192
|
+
## Best Practices Demonstrated
|
|
1193
|
+
|
|
1194
|
+
### Security
|
|
1195
|
+
✅ Capability checks (`current_user_can('manage_options')`)
|
|
1196
|
+
✅ Automatic nonce verification (Settings API)
|
|
1197
|
+
✅ Input sanitization (all fields)
|
|
1198
|
+
✅ Output escaping (`esc_html`, `esc_attr`, `esc_url`)
|
|
1199
|
+
✅ Validation with error messages
|
|
1200
|
+
|
|
1201
|
+
### WordPress Standards
|
|
1202
|
+
✅ Settings API usage
|
|
1203
|
+
✅ Internationalization (`__()`, `_e()`)
|
|
1204
|
+
✅ Proper hook usage (`admin_menu`, `admin_init`)
|
|
1205
|
+
✅ Autoloader for class files
|
|
1206
|
+
✅ Proper file organization
|
|
1207
|
+
✅ WordPress coding standards
|
|
1208
|
+
|
|
1209
|
+
### User Experience
|
|
1210
|
+
✅ Clear section organization
|
|
1211
|
+
✅ Helpful field descriptions
|
|
1212
|
+
✅ Validation feedback
|
|
1213
|
+
✅ Sidebar with documentation
|
|
1214
|
+
✅ Responsive layout
|
|
1215
|
+
✅ Color picker integration
|
|
1216
|
+
|
|
1217
|
+
### Code Quality
|
|
1218
|
+
✅ Separation of concerns (page, fields, validation)
|
|
1219
|
+
✅ Reusable field rendering methods
|
|
1220
|
+
✅ Consistent naming conventions
|
|
1221
|
+
✅ Proper documentation
|
|
1222
|
+
✅ Clean uninstall process
|
|
1223
|
+
|
|
1224
|
+
---
|
|
1225
|
+
|
|
1226
|
+
## Customization
|
|
1227
|
+
|
|
1228
|
+
### Add New Field Type
|
|
1229
|
+
|
|
1230
|
+
```php
|
|
1231
|
+
<?php
|
|
1232
|
+
// In class-settings-fields.php
|
|
1233
|
+
public static function render_custom_field($args) {
|
|
1234
|
+
$option_name = $args['option_name'];
|
|
1235
|
+
$value = get_option($option_name, '');
|
|
1236
|
+
$description = isset($args['description']) ? $args['description'] : '';
|
|
1237
|
+
|
|
1238
|
+
// Custom field HTML
|
|
1239
|
+
printf(
|
|
1240
|
+
'<input type="text" id="%s" name="%s" value="%s" class="custom-field">',
|
|
1241
|
+
esc_attr($args['label_for']),
|
|
1242
|
+
esc_attr($option_name),
|
|
1243
|
+
esc_attr($value)
|
|
1244
|
+
);
|
|
1245
|
+
|
|
1246
|
+
if ($description) {
|
|
1247
|
+
printf('<p class="description">%s</p>', esc_html($description));
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
?>
|
|
1251
|
+
```
|
|
1252
|
+
|
|
1253
|
+
### Add Tabs to Settings Page
|
|
1254
|
+
|
|
1255
|
+
```php
|
|
1256
|
+
<?php
|
|
1257
|
+
// Add to settings-page.php view
|
|
1258
|
+
<h2 class="nav-tab-wrapper">
|
|
1259
|
+
<a href="?page=site-settings-manager&tab=general" class="nav-tab <?php echo $active_tab == 'general' ? 'nav-tab-active' : ''; ?>">
|
|
1260
|
+
<?php _e('General', 'site-settings-manager'); ?>
|
|
1261
|
+
</a>
|
|
1262
|
+
<a href="?page=site-settings-manager&tab=advanced" class="nav-tab <?php echo $active_tab == 'advanced' ? 'nav-tab-active' : ''; ?>">
|
|
1263
|
+
<?php _e('Advanced', 'site-settings-manager'); ?>
|
|
1264
|
+
</a>
|
|
1265
|
+
</h2>
|
|
1266
|
+
?>
|
|
1267
|
+
```
|
|
1268
|
+
|
|
1269
|
+
### Export/Import Settings
|
|
1270
|
+
|
|
1271
|
+
```php
|
|
1272
|
+
<?php
|
|
1273
|
+
// Export settings
|
|
1274
|
+
function ssm_export_settings() {
|
|
1275
|
+
$settings = array(
|
|
1276
|
+
'ssm_site_title' => get_option('ssm_site_title'),
|
|
1277
|
+
'ssm_site_description' => get_option('ssm_site_description'),
|
|
1278
|
+
// ... other settings
|
|
1279
|
+
);
|
|
1280
|
+
|
|
1281
|
+
return json_encode($settings);
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
// Import settings
|
|
1285
|
+
function ssm_import_settings($json) {
|
|
1286
|
+
$settings = json_decode($json, true);
|
|
1287
|
+
|
|
1288
|
+
if ($settings) {
|
|
1289
|
+
foreach ($settings as $key => $value) {
|
|
1290
|
+
update_option($key, $value);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
?>
|
|
1295
|
+
```
|
|
1296
|
+
|
|
1297
|
+
---
|
|
1298
|
+
|
|
1299
|
+
## Testing Checklist
|
|
1300
|
+
|
|
1301
|
+
- [ ] Access settings page (Settings > Site Settings)
|
|
1302
|
+
- [ ] Save settings with valid values
|
|
1303
|
+
- [ ] Test validation errors (invalid API key, out-of-range numbers)
|
|
1304
|
+
- [ ] Test email list validation
|
|
1305
|
+
- [ ] Test color picker functionality
|
|
1306
|
+
- [ ] Test checkbox toggle
|
|
1307
|
+
- [ ] Verify settings persist after save
|
|
1308
|
+
- [ ] Test responsive layout on mobile
|
|
1309
|
+
- [ ] Verify capability checks (non-admin users)
|
|
1310
|
+
- [ ] Test uninstall cleanup
|
|
1311
|
+
- [ ] Check for PHP/JavaScript errors
|
|
1312
|
+
- [ ] Verify internationalization strings
|
|
1313
|
+
|
|
1314
|
+
---
|
|
1315
|
+
|
|
1316
|
+
## Comparison with Other Patterns
|
|
1317
|
+
|
|
1318
|
+
| Feature | This Plugin | Simple Settings | Advanced Settings | Framework-Based |
|
|
1319
|
+
|---------|-------------|-----------------|-------------------|-----------------|
|
|
1320
|
+
| **Complexity** | Medium | Low | High | Very High |
|
|
1321
|
+
| **File Count** | 5-10 | 1-2 | 10-20 | 20+ |
|
|
1322
|
+
| **Settings API** | ✅ Full | ✅ Basic | ✅ Full | ✅ Custom |
|
|
1323
|
+
| **Validation** | ✅ Advanced | ❌ | ✅ Advanced | ✅ Advanced |
|
|
1324
|
+
| **Field Types** | ✅ 7 types | ✅ 2-3 types | ✅ 10+ types | ✅ Unlimited |
|
|
1325
|
+
| **Layout** | ✅ Custom | ❌ Basic | ✅ Tabbed | ✅ Advanced |
|
|
1326
|
+
| **Security** | ✅ Full | ✅ Basic | ✅ Full | ✅ Full |
|
|
1327
|
+
| **Best For** | Most plugins | Simple config | Complex plugins | Large systems |
|
|
1328
|
+
|
|
1329
|
+
---
|
|
1330
|
+
|
|
1331
|
+
## Summary
|
|
1332
|
+
|
|
1333
|
+
This example demonstrates a **complete settings page plugin** with:
|
|
1334
|
+
|
|
1335
|
+
- ✅ WordPress Settings API integration
|
|
1336
|
+
- ✅ Multiple field types (text, textarea, checkbox, password, number, color, select, radio)
|
|
1337
|
+
- ✅ Advanced validation and sanitization
|
|
1338
|
+
- ✅ Custom admin page with sidebar
|
|
1339
|
+
- ✅ Proper security (capability checks, sanitization, escaping)
|
|
1340
|
+
- ✅ Error handling and user feedback
|
|
1341
|
+
- ✅ Responsive design
|
|
1342
|
+
- ✅ Color picker integration
|
|
1343
|
+
- ✅ Clean uninstall process
|
|
1344
|
+
- ✅ Internationalization support
|
|
1345
|
+
- ✅ Reusable field rendering methods
|
|
1346
|
+
|
|
1347
|
+
**Perfect for**: Plugin configuration, site settings, feature toggles, API integrations, or any plugin requiring user-configurable options.
|
|
1348
|
+
|
|
1349
|
+
**Character Count**: ~24,500 characters
|
|
1350
|
+
|