@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,971 @@
|
|
|
1
|
+
# Singleton Plugin Example
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This example demonstrates the **Singleton Design Pattern** - ensuring a class has only one instance with global access point, commonly used in WordPress plugin development.
|
|
6
|
+
|
|
7
|
+
**Complexity**: Medium
|
|
8
|
+
**File Count**: 5-15 files
|
|
9
|
+
**Team Size**: 1-3 developers
|
|
10
|
+
**Use Case**: Plugin main class, database connections, cache managers, configuration managers
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Complete Plugin: "Settings Manager Singleton"
|
|
15
|
+
|
|
16
|
+
A complete settings management plugin demonstrating the Singleton pattern for the main plugin class and various manager classes.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Directory Structure
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
settings-manager-singleton/
|
|
24
|
+
├── settings-manager-singleton.php # Main plugin file (bootstrap)
|
|
25
|
+
├── uninstall.php # Uninstall cleanup
|
|
26
|
+
├── readme.txt # WordPress.org readme
|
|
27
|
+
├── includes/
|
|
28
|
+
│ ├── class-settings-manager.php # Main plugin class (Singleton)
|
|
29
|
+
│ ├── class-database.php # Database manager (Singleton)
|
|
30
|
+
│ ├── class-cache.php # Cache manager (Singleton)
|
|
31
|
+
│ ├── class-config.php # Config manager (Singleton)
|
|
32
|
+
│ └── class-logger.php # Logger (Singleton)
|
|
33
|
+
├── admin/
|
|
34
|
+
│ ├── class-admin.php # Admin functionality
|
|
35
|
+
│ └── views/
|
|
36
|
+
│ └── settings-page.php # Settings view
|
|
37
|
+
├── public/
|
|
38
|
+
│ └── class-public.php # Public functionality
|
|
39
|
+
└── assets/
|
|
40
|
+
├── css/
|
|
41
|
+
└── js/
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Main Plugin File
|
|
47
|
+
|
|
48
|
+
### File: `settings-manager-singleton.php`
|
|
49
|
+
|
|
50
|
+
```php
|
|
51
|
+
<?php
|
|
52
|
+
/**
|
|
53
|
+
* Plugin Name: Settings Manager Singleton
|
|
54
|
+
* Plugin URI: https://example.com/settings-manager
|
|
55
|
+
* Description: Settings management with Singleton pattern
|
|
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: settings-manager-singleton
|
|
62
|
+
* Domain Path: /languages
|
|
63
|
+
*
|
|
64
|
+
* @package Settings_Manager_Singleton
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
// Exit if accessed directly
|
|
68
|
+
if (!defined('ABSPATH')) {
|
|
69
|
+
exit;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Define plugin constants
|
|
73
|
+
define('SMS_VERSION', '1.0.0');
|
|
74
|
+
define('SMS_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
|
75
|
+
define('SMS_PLUGIN_URL', plugin_dir_url(__FILE__));
|
|
76
|
+
define('SMS_PLUGIN_FILE', __FILE__);
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Autoloader
|
|
80
|
+
*/
|
|
81
|
+
spl_autoload_register(function ($class) {
|
|
82
|
+
$prefix = 'Settings_Manager_';
|
|
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
|
+
// Check includes directory
|
|
92
|
+
$file = SMS_PLUGIN_DIR . 'includes/' . $class_file;
|
|
93
|
+
if (file_exists($file)) {
|
|
94
|
+
require $file;
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Check admin directory
|
|
99
|
+
$file = SMS_PLUGIN_DIR . 'admin/' . $class_file;
|
|
100
|
+
if (file_exists($file)) {
|
|
101
|
+
require $file;
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Check public directory
|
|
106
|
+
$file = SMS_PLUGIN_DIR . 'public/' . $class_file;
|
|
107
|
+
if (file_exists($file)) {
|
|
108
|
+
require $file;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Activation hook
|
|
114
|
+
*/
|
|
115
|
+
register_activation_hook(__FILE__, function() {
|
|
116
|
+
Settings_Manager_Singleton::get_instance()->activate();
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Deactivation hook
|
|
121
|
+
*/
|
|
122
|
+
register_deactivation_hook(__FILE__, function() {
|
|
123
|
+
Settings_Manager_Singleton::get_instance()->deactivate();
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Initialize the plugin
|
|
128
|
+
*
|
|
129
|
+
* Use the Singleton pattern to get the plugin instance
|
|
130
|
+
*/
|
|
131
|
+
function run_settings_manager_singleton() {
|
|
132
|
+
return Settings_Manager_Singleton::get_instance();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Run the plugin
|
|
136
|
+
run_settings_manager_singleton();
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Singleton Pattern Implementation
|
|
142
|
+
|
|
143
|
+
### File: `includes/class-settings-manager.php`
|
|
144
|
+
|
|
145
|
+
```php
|
|
146
|
+
<?php
|
|
147
|
+
/**
|
|
148
|
+
* Main plugin class using Singleton pattern
|
|
149
|
+
*
|
|
150
|
+
* @package Settings_Manager_Singleton
|
|
151
|
+
*/
|
|
152
|
+
|
|
153
|
+
class Settings_Manager_Singleton {
|
|
154
|
+
/**
|
|
155
|
+
* The single instance of the class
|
|
156
|
+
*
|
|
157
|
+
* @var Settings_Manager_Singleton
|
|
158
|
+
*/
|
|
159
|
+
private static $instance = null;
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Plugin version
|
|
163
|
+
*
|
|
164
|
+
* @var string
|
|
165
|
+
*/
|
|
166
|
+
private $version;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Database manager instance
|
|
170
|
+
*
|
|
171
|
+
* @var Settings_Manager_Database
|
|
172
|
+
*/
|
|
173
|
+
private $database;
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Cache manager instance
|
|
177
|
+
*
|
|
178
|
+
* @var Settings_Manager_Cache
|
|
179
|
+
*/
|
|
180
|
+
private $cache;
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Config manager instance
|
|
184
|
+
*
|
|
185
|
+
* @var Settings_Manager_Config
|
|
186
|
+
*/
|
|
187
|
+
private $config;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Private constructor to prevent direct instantiation
|
|
191
|
+
*
|
|
192
|
+
* This is the key to the Singleton pattern - the constructor is private
|
|
193
|
+
* so new instances cannot be created with 'new Settings_Manager_Singleton()'
|
|
194
|
+
*/
|
|
195
|
+
private function __construct() {
|
|
196
|
+
$this->version = SMS_VERSION;
|
|
197
|
+
|
|
198
|
+
$this->load_dependencies();
|
|
199
|
+
$this->set_locale();
|
|
200
|
+
$this->define_admin_hooks();
|
|
201
|
+
$this->define_public_hooks();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Prevent cloning of the instance
|
|
206
|
+
*
|
|
207
|
+
* Singleton pattern requirement - prevent cloning
|
|
208
|
+
*/
|
|
209
|
+
private function __clone() {
|
|
210
|
+
// Prevent cloning
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Prevent unserializing of the instance
|
|
215
|
+
*
|
|
216
|
+
* Singleton pattern requirement - prevent unserialization
|
|
217
|
+
*/
|
|
218
|
+
public function __wakeup() {
|
|
219
|
+
throw new Exception("Cannot unserialize singleton");
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Get the single instance of the class
|
|
224
|
+
*
|
|
225
|
+
* This is the public static method that returns the single instance
|
|
226
|
+
*
|
|
227
|
+
* @return Settings_Manager_Singleton
|
|
228
|
+
*/
|
|
229
|
+
public static function get_instance() {
|
|
230
|
+
if (self::$instance === null) {
|
|
231
|
+
self::$instance = new self();
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return self::$instance;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Load required dependencies
|
|
239
|
+
*/
|
|
240
|
+
private function load_dependencies() {
|
|
241
|
+
// Get singleton instances of manager classes
|
|
242
|
+
$this->database = Settings_Manager_Database::get_instance();
|
|
243
|
+
$this->cache = Settings_Manager_Cache::get_instance();
|
|
244
|
+
$this->config = Settings_Manager_Config::get_instance();
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Set the plugin locale for internationalization
|
|
249
|
+
*/
|
|
250
|
+
private function set_locale() {
|
|
251
|
+
add_action('plugins_loaded', array($this, 'load_plugin_textdomain'));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Load plugin text domain
|
|
256
|
+
*/
|
|
257
|
+
public function load_plugin_textdomain() {
|
|
258
|
+
load_plugin_textdomain(
|
|
259
|
+
'settings-manager-singleton',
|
|
260
|
+
false,
|
|
261
|
+
dirname(plugin_basename(SMS_PLUGIN_FILE)) . '/languages/'
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Register admin hooks
|
|
267
|
+
*/
|
|
268
|
+
private function define_admin_hooks() {
|
|
269
|
+
if (is_admin()) {
|
|
270
|
+
$admin = new Settings_Manager_Admin($this->version);
|
|
271
|
+
|
|
272
|
+
add_action('admin_menu', array($admin, 'add_admin_menu'));
|
|
273
|
+
add_action('admin_init', array($admin, 'register_settings'));
|
|
274
|
+
add_action('admin_enqueue_scripts', array($admin, 'enqueue_styles'));
|
|
275
|
+
add_action('admin_enqueue_scripts', array($admin, 'enqueue_scripts'));
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Register public hooks
|
|
281
|
+
*/
|
|
282
|
+
private function define_public_hooks() {
|
|
283
|
+
$public = new Settings_Manager_Public($this->version);
|
|
284
|
+
|
|
285
|
+
add_action('wp_enqueue_scripts', array($public, 'enqueue_styles'));
|
|
286
|
+
add_action('wp_enqueue_scripts', array($public, 'enqueue_scripts'));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Activation hook
|
|
291
|
+
*/
|
|
292
|
+
public function activate() {
|
|
293
|
+
// Create database tables
|
|
294
|
+
$this->database->create_tables();
|
|
295
|
+
|
|
296
|
+
// Set default options
|
|
297
|
+
$this->config->set_defaults();
|
|
298
|
+
|
|
299
|
+
// Clear cache
|
|
300
|
+
$this->cache->flush();
|
|
301
|
+
|
|
302
|
+
// Log activation
|
|
303
|
+
Settings_Manager_Logger::get_instance()->log('Plugin activated');
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Deactivation hook
|
|
308
|
+
*/
|
|
309
|
+
public function deactivate() {
|
|
310
|
+
// Clear cache
|
|
311
|
+
$this->cache->flush();
|
|
312
|
+
|
|
313
|
+
// Log deactivation
|
|
314
|
+
Settings_Manager_Logger::get_instance()->log('Plugin deactivated');
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Get plugin version
|
|
319
|
+
*
|
|
320
|
+
* @return string
|
|
321
|
+
*/
|
|
322
|
+
public function get_version() {
|
|
323
|
+
return $this->version;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Get database manager
|
|
328
|
+
*
|
|
329
|
+
* @return Settings_Manager_Database
|
|
330
|
+
*/
|
|
331
|
+
public function get_database() {
|
|
332
|
+
return $this->database;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Get cache manager
|
|
337
|
+
*
|
|
338
|
+
* @return Settings_Manager_Cache
|
|
339
|
+
*/
|
|
340
|
+
public function get_cache() {
|
|
341
|
+
return $this->cache;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Get config manager
|
|
346
|
+
*
|
|
347
|
+
* @return Settings_Manager_Config
|
|
348
|
+
*/
|
|
349
|
+
public function get_config() {
|
|
350
|
+
return $this->config;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### File: `includes/class-database.php`
|
|
356
|
+
|
|
357
|
+
```php
|
|
358
|
+
<?php
|
|
359
|
+
/**
|
|
360
|
+
* Database manager using Singleton pattern
|
|
361
|
+
*
|
|
362
|
+
* @package Settings_Manager_Singleton
|
|
363
|
+
*/
|
|
364
|
+
|
|
365
|
+
class Settings_Manager_Database {
|
|
366
|
+
/**
|
|
367
|
+
* The single instance of the class
|
|
368
|
+
*
|
|
369
|
+
* @var Settings_Manager_Database
|
|
370
|
+
*/
|
|
371
|
+
private static $instance = null;
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* WordPress database object
|
|
375
|
+
*
|
|
376
|
+
* @var wpdb
|
|
377
|
+
*/
|
|
378
|
+
private $wpdb;
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Table name
|
|
382
|
+
*
|
|
383
|
+
* @var string
|
|
384
|
+
*/
|
|
385
|
+
private $table_name;
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Private constructor
|
|
389
|
+
*/
|
|
390
|
+
private function __construct() {
|
|
391
|
+
global $wpdb;
|
|
392
|
+
$this->wpdb = $wpdb;
|
|
393
|
+
$this->table_name = $wpdb->prefix . 'sms_settings';
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Prevent cloning
|
|
398
|
+
*/
|
|
399
|
+
private function __clone() {
|
|
400
|
+
// Prevent cloning
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Prevent unserialization
|
|
405
|
+
*/
|
|
406
|
+
public function __wakeup() {
|
|
407
|
+
throw new Exception("Cannot unserialize singleton");
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Get the single instance
|
|
412
|
+
*
|
|
413
|
+
* @return Settings_Manager_Database
|
|
414
|
+
*/
|
|
415
|
+
public static function get_instance() {
|
|
416
|
+
if (self::$instance === null) {
|
|
417
|
+
self::$instance = new self();
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return self::$instance;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Create database tables
|
|
425
|
+
*/
|
|
426
|
+
public function create_tables() {
|
|
427
|
+
$charset_collate = $this->wpdb->get_charset_collate();
|
|
428
|
+
|
|
429
|
+
$sql = "CREATE TABLE {$this->table_name} (
|
|
430
|
+
id bigint(20) NOT NULL AUTO_INCREMENT,
|
|
431
|
+
setting_key varchar(100) NOT NULL,
|
|
432
|
+
setting_value longtext,
|
|
433
|
+
setting_type varchar(20) DEFAULT 'string',
|
|
434
|
+
created_at datetime DEFAULT CURRENT_TIMESTAMP,
|
|
435
|
+
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
436
|
+
PRIMARY KEY (id),
|
|
437
|
+
UNIQUE KEY setting_key (setting_key)
|
|
438
|
+
) $charset_collate;";
|
|
439
|
+
|
|
440
|
+
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
|
441
|
+
dbDelta($sql);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Get setting value
|
|
446
|
+
*
|
|
447
|
+
* @param string $key Setting key
|
|
448
|
+
* @param mixed $default Default value
|
|
449
|
+
* @return mixed
|
|
450
|
+
*/
|
|
451
|
+
public function get($key, $default = null) {
|
|
452
|
+
$result = $this->wpdb->get_row(
|
|
453
|
+
$this->wpdb->prepare(
|
|
454
|
+
"SELECT setting_value, setting_type FROM {$this->table_name} WHERE setting_key = %s",
|
|
455
|
+
$key
|
|
456
|
+
)
|
|
457
|
+
);
|
|
458
|
+
|
|
459
|
+
if (!$result) {
|
|
460
|
+
return $default;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return $this->unserialize_value($result->setting_value, $result->setting_type);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Set setting value
|
|
468
|
+
*
|
|
469
|
+
* @param string $key Setting key
|
|
470
|
+
* @param mixed $value Setting value
|
|
471
|
+
* @return bool
|
|
472
|
+
*/
|
|
473
|
+
public function set($key, $value) {
|
|
474
|
+
$type = $this->get_value_type($value);
|
|
475
|
+
$serialized_value = $this->serialize_value($value, $type);
|
|
476
|
+
|
|
477
|
+
$existing = $this->wpdb->get_var(
|
|
478
|
+
$this->wpdb->prepare(
|
|
479
|
+
"SELECT id FROM {$this->table_name} WHERE setting_key = %s",
|
|
480
|
+
$key
|
|
481
|
+
)
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
if ($existing) {
|
|
485
|
+
return $this->wpdb->update(
|
|
486
|
+
$this->table_name,
|
|
487
|
+
array(
|
|
488
|
+
'setting_value' => $serialized_value,
|
|
489
|
+
'setting_type' => $type,
|
|
490
|
+
),
|
|
491
|
+
array('setting_key' => $key)
|
|
492
|
+
) !== false;
|
|
493
|
+
} else {
|
|
494
|
+
return $this->wpdb->insert(
|
|
495
|
+
$this->table_name,
|
|
496
|
+
array(
|
|
497
|
+
'setting_key' => $key,
|
|
498
|
+
'setting_value' => $serialized_value,
|
|
499
|
+
'setting_type' => $type,
|
|
500
|
+
)
|
|
501
|
+
) !== false;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Delete setting
|
|
507
|
+
*
|
|
508
|
+
* @param string $key Setting key
|
|
509
|
+
* @return bool
|
|
510
|
+
*/
|
|
511
|
+
public function delete($key) {
|
|
512
|
+
return $this->wpdb->delete(
|
|
513
|
+
$this->table_name,
|
|
514
|
+
array('setting_key' => $key)
|
|
515
|
+
) !== false;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Get value type
|
|
520
|
+
*
|
|
521
|
+
* @param mixed $value Value
|
|
522
|
+
* @return string
|
|
523
|
+
*/
|
|
524
|
+
private function get_value_type($value) {
|
|
525
|
+
if (is_array($value)) {
|
|
526
|
+
return 'array';
|
|
527
|
+
} elseif (is_object($value)) {
|
|
528
|
+
return 'object';
|
|
529
|
+
} elseif (is_bool($value)) {
|
|
530
|
+
return 'boolean';
|
|
531
|
+
} elseif (is_int($value)) {
|
|
532
|
+
return 'integer';
|
|
533
|
+
} elseif (is_float($value)) {
|
|
534
|
+
return 'float';
|
|
535
|
+
} else {
|
|
536
|
+
return 'string';
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Serialize value
|
|
542
|
+
*
|
|
543
|
+
* @param mixed $value Value
|
|
544
|
+
* @param string $type Type
|
|
545
|
+
* @return string
|
|
546
|
+
*/
|
|
547
|
+
private function serialize_value($value, $type) {
|
|
548
|
+
if ($type === 'array' || $type === 'object') {
|
|
549
|
+
return maybe_serialize($value);
|
|
550
|
+
} elseif ($type === 'boolean') {
|
|
551
|
+
return $value ? '1' : '0';
|
|
552
|
+
} else {
|
|
553
|
+
return (string) $value;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Unserialize value
|
|
559
|
+
*
|
|
560
|
+
* @param string $value Serialized value
|
|
561
|
+
* @param string $type Type
|
|
562
|
+
* @return mixed
|
|
563
|
+
*/
|
|
564
|
+
private function unserialize_value($value, $type) {
|
|
565
|
+
if ($type === 'array' || $type === 'object') {
|
|
566
|
+
return maybe_unserialize($value);
|
|
567
|
+
} elseif ($type === 'boolean') {
|
|
568
|
+
return $value === '1';
|
|
569
|
+
} elseif ($type === 'integer') {
|
|
570
|
+
return (int) $value;
|
|
571
|
+
} elseif ($type === 'float') {
|
|
572
|
+
return (float) $value;
|
|
573
|
+
} else {
|
|
574
|
+
return $value;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
### File: `includes/class-cache.php`
|
|
581
|
+
|
|
582
|
+
```php
|
|
583
|
+
<?php
|
|
584
|
+
/**
|
|
585
|
+
* Cache manager using Singleton pattern
|
|
586
|
+
*
|
|
587
|
+
* @package Settings_Manager_Singleton
|
|
588
|
+
*/
|
|
589
|
+
|
|
590
|
+
class Settings_Manager_Cache {
|
|
591
|
+
/**
|
|
592
|
+
* The single instance of the class
|
|
593
|
+
*
|
|
594
|
+
* @var Settings_Manager_Cache
|
|
595
|
+
*/
|
|
596
|
+
private static $instance = null;
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Cache group
|
|
600
|
+
*
|
|
601
|
+
* @var string
|
|
602
|
+
*/
|
|
603
|
+
private $cache_group = 'sms_cache';
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Private constructor
|
|
607
|
+
*/
|
|
608
|
+
private function __construct() {
|
|
609
|
+
// Constructor logic
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Prevent cloning
|
|
614
|
+
*/
|
|
615
|
+
private function __clone() {
|
|
616
|
+
// Prevent cloning
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Prevent unserialization
|
|
621
|
+
*/
|
|
622
|
+
public function __wakeup() {
|
|
623
|
+
throw new Exception("Cannot unserialize singleton");
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Get the single instance
|
|
628
|
+
*
|
|
629
|
+
* @return Settings_Manager_Cache
|
|
630
|
+
*/
|
|
631
|
+
public static function get_instance() {
|
|
632
|
+
if (self::$instance === null) {
|
|
633
|
+
self::$instance = new self();
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return self::$instance;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Get cached value
|
|
641
|
+
*
|
|
642
|
+
* @param string $key Cache key
|
|
643
|
+
* @param mixed $default Default value
|
|
644
|
+
* @return mixed
|
|
645
|
+
*/
|
|
646
|
+
public function get($key, $default = null) {
|
|
647
|
+
$value = wp_cache_get($key, $this->cache_group);
|
|
648
|
+
|
|
649
|
+
if ($value === false) {
|
|
650
|
+
return $default;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
return $value;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
/**
|
|
657
|
+
* Set cached value
|
|
658
|
+
*
|
|
659
|
+
* @param string $key Cache key
|
|
660
|
+
* @param mixed $value Value to cache
|
|
661
|
+
* @param int $expiration Expiration in seconds (default: 1 hour)
|
|
662
|
+
* @return bool
|
|
663
|
+
*/
|
|
664
|
+
public function set($key, $value, $expiration = 3600) {
|
|
665
|
+
return wp_cache_set($key, $value, $this->cache_group, $expiration);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* Delete cached value
|
|
670
|
+
*
|
|
671
|
+
* @param string $key Cache key
|
|
672
|
+
* @return bool
|
|
673
|
+
*/
|
|
674
|
+
public function delete($key) {
|
|
675
|
+
return wp_cache_delete($key, $this->cache_group);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Flush all cache
|
|
680
|
+
*
|
|
681
|
+
* @return bool
|
|
682
|
+
*/
|
|
683
|
+
public function flush() {
|
|
684
|
+
return wp_cache_flush();
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* Remember - get from cache or execute callback and cache result
|
|
689
|
+
*
|
|
690
|
+
* @param string $key Cache key
|
|
691
|
+
* @param callable $callback Callback to execute if cache miss
|
|
692
|
+
* @param int $expiration Expiration in seconds
|
|
693
|
+
* @return mixed
|
|
694
|
+
*/
|
|
695
|
+
public function remember($key, $callback, $expiration = 3600) {
|
|
696
|
+
$value = $this->get($key);
|
|
697
|
+
|
|
698
|
+
if ($value !== null) {
|
|
699
|
+
return $value;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
$value = call_user_func($callback);
|
|
703
|
+
$this->set($key, $value, $expiration);
|
|
704
|
+
|
|
705
|
+
return $value;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
### File: `includes/class-config.php`
|
|
711
|
+
|
|
712
|
+
```php
|
|
713
|
+
<?php
|
|
714
|
+
/**
|
|
715
|
+
* Config manager using Singleton pattern
|
|
716
|
+
*
|
|
717
|
+
* @package Settings_Manager_Singleton
|
|
718
|
+
*/
|
|
719
|
+
|
|
720
|
+
class Settings_Manager_Config {
|
|
721
|
+
/**
|
|
722
|
+
* The single instance of the class
|
|
723
|
+
*
|
|
724
|
+
* @var Settings_Manager_Config
|
|
725
|
+
*/
|
|
726
|
+
private static $instance = null;
|
|
727
|
+
|
|
728
|
+
/**
|
|
729
|
+
* Configuration array
|
|
730
|
+
*
|
|
731
|
+
* @var array
|
|
732
|
+
*/
|
|
733
|
+
private $config = array();
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* Private constructor
|
|
737
|
+
*/
|
|
738
|
+
private function __construct() {
|
|
739
|
+
$this->load_config();
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* Prevent cloning
|
|
744
|
+
*/
|
|
745
|
+
private function __clone() {
|
|
746
|
+
// Prevent cloning
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Prevent unserialization
|
|
751
|
+
*/
|
|
752
|
+
public function __wakeup() {
|
|
753
|
+
throw new Exception("Cannot unserialize singleton");
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Get the single instance
|
|
758
|
+
*
|
|
759
|
+
* @return Settings_Manager_Config
|
|
760
|
+
*/
|
|
761
|
+
public static function get_instance() {
|
|
762
|
+
if (self::$instance === null) {
|
|
763
|
+
self::$instance = new self();
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
return self::$instance;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* Load configuration
|
|
771
|
+
*/
|
|
772
|
+
private function load_config() {
|
|
773
|
+
$this->config = array(
|
|
774
|
+
'version' => SMS_VERSION,
|
|
775
|
+
'plugin_dir' => SMS_PLUGIN_DIR,
|
|
776
|
+
'plugin_url' => SMS_PLUGIN_URL,
|
|
777
|
+
'cache_enabled' => true,
|
|
778
|
+
'cache_expiration' => 3600,
|
|
779
|
+
'debug_mode' => defined('WP_DEBUG') && WP_DEBUG,
|
|
780
|
+
);
|
|
781
|
+
|
|
782
|
+
// Allow filtering
|
|
783
|
+
$this->config = apply_filters('sms_config', $this->config);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
/**
|
|
787
|
+
* Get config value
|
|
788
|
+
*
|
|
789
|
+
* @param string $key Config key (supports dot notation)
|
|
790
|
+
* @param mixed $default Default value
|
|
791
|
+
* @return mixed
|
|
792
|
+
*/
|
|
793
|
+
public function get($key, $default = null) {
|
|
794
|
+
// Support dot notation (e.g., 'cache.enabled')
|
|
795
|
+
$keys = explode('.', $key);
|
|
796
|
+
$value = $this->config;
|
|
797
|
+
|
|
798
|
+
foreach ($keys as $k) {
|
|
799
|
+
if (!isset($value[$k])) {
|
|
800
|
+
return $default;
|
|
801
|
+
}
|
|
802
|
+
$value = $value[$k];
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
return $value;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
/**
|
|
809
|
+
* Set config value
|
|
810
|
+
*
|
|
811
|
+
* @param string $key Config key
|
|
812
|
+
* @param mixed $value Config value
|
|
813
|
+
*/
|
|
814
|
+
public function set($key, $value) {
|
|
815
|
+
$this->config[$key] = $value;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/**
|
|
819
|
+
* Check if config key exists
|
|
820
|
+
*
|
|
821
|
+
* @param string $key Config key
|
|
822
|
+
* @return bool
|
|
823
|
+
*/
|
|
824
|
+
public function has($key) {
|
|
825
|
+
return isset($this->config[$key]);
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
/**
|
|
829
|
+
* Get all config
|
|
830
|
+
*
|
|
831
|
+
* @return array
|
|
832
|
+
*/
|
|
833
|
+
public function all() {
|
|
834
|
+
return $this->config;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* Set default options
|
|
839
|
+
*/
|
|
840
|
+
public function set_defaults() {
|
|
841
|
+
$defaults = array(
|
|
842
|
+
'sms_enabled' => true,
|
|
843
|
+
'sms_cache_enabled' => true,
|
|
844
|
+
'sms_debug_mode' => false,
|
|
845
|
+
);
|
|
846
|
+
|
|
847
|
+
foreach ($defaults as $key => $value) {
|
|
848
|
+
if (get_option($key) === false) {
|
|
849
|
+
add_option($key, $value);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
### File: `includes/class-logger.php`
|
|
857
|
+
|
|
858
|
+
```php
|
|
859
|
+
<?php
|
|
860
|
+
/**
|
|
861
|
+
* Logger using Singleton pattern
|
|
862
|
+
*
|
|
863
|
+
* @package Settings_Manager_Singleton
|
|
864
|
+
*/
|
|
865
|
+
|
|
866
|
+
class Settings_Manager_Logger {
|
|
867
|
+
/**
|
|
868
|
+
* The single instance of the class
|
|
869
|
+
*
|
|
870
|
+
* @var Settings_Manager_Logger
|
|
871
|
+
*/
|
|
872
|
+
private static $instance = null;
|
|
873
|
+
|
|
874
|
+
/**
|
|
875
|
+
* Log file path
|
|
876
|
+
*
|
|
877
|
+
* @var string
|
|
878
|
+
*/
|
|
879
|
+
private $log_file;
|
|
880
|
+
|
|
881
|
+
/**
|
|
882
|
+
* Private constructor
|
|
883
|
+
*/
|
|
884
|
+
private function __construct() {
|
|
885
|
+
$upload_dir = wp_upload_dir();
|
|
886
|
+
$this->log_file = $upload_dir['basedir'] . '/sms-debug.log';
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
/**
|
|
890
|
+
* Prevent cloning
|
|
891
|
+
*/
|
|
892
|
+
private function __clone() {
|
|
893
|
+
// Prevent cloning
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* Prevent unserialization
|
|
898
|
+
*/
|
|
899
|
+
public function __wakeup() {
|
|
900
|
+
throw new Exception("Cannot unserialize singleton");
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
/**
|
|
904
|
+
* Get the single instance
|
|
905
|
+
*
|
|
906
|
+
* @return Settings_Manager_Logger
|
|
907
|
+
*/
|
|
908
|
+
public static function get_instance() {
|
|
909
|
+
if (self::$instance === null) {
|
|
910
|
+
self::$instance = new self();
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
return self::$instance;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
/**
|
|
917
|
+
* Log message
|
|
918
|
+
*
|
|
919
|
+
* @param string $message Log message
|
|
920
|
+
* @param string $level Log level (info, warning, error)
|
|
921
|
+
*/
|
|
922
|
+
public function log($message, $level = 'info') {
|
|
923
|
+
if (!Settings_Manager_Config::get_instance()->get('debug_mode')) {
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
$timestamp = current_time('Y-m-d H:i:s');
|
|
928
|
+
$formatted_message = "[{$timestamp}] [{$level}] {$message}\n";
|
|
929
|
+
|
|
930
|
+
error_log($formatted_message, 3, $this->log_file);
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/**
|
|
934
|
+
* Log info message
|
|
935
|
+
*
|
|
936
|
+
* @param string $message Message
|
|
937
|
+
*/
|
|
938
|
+
public function info($message) {
|
|
939
|
+
$this->log($message, 'info');
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* Log warning message
|
|
944
|
+
*
|
|
945
|
+
* @param string $message Message
|
|
946
|
+
*/
|
|
947
|
+
public function warning($message) {
|
|
948
|
+
$this->log($message, 'warning');
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
/**
|
|
952
|
+
* Log error message
|
|
953
|
+
*
|
|
954
|
+
* @param string $message Message
|
|
955
|
+
*/
|
|
956
|
+
public function error($message) {
|
|
957
|
+
$this->log($message, 'error');
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* Clear log file
|
|
962
|
+
*/
|
|
963
|
+
public function clear() {
|
|
964
|
+
if (file_exists($this->log_file)) {
|
|
965
|
+
unlink($this->log_file);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
```
|
|
970
|
+
|
|
971
|
+
|