@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,949 @@
|
|
|
1
|
+
# WooCommerce Integration for WordPress Plugins
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This document provides comprehensive guidelines for creating WordPress plugins that integrate with WooCommerce, the most popular eCommerce platform for WordPress.
|
|
6
|
+
|
|
7
|
+
## Plugin Detection
|
|
8
|
+
|
|
9
|
+
### Check if WooCommerce is Active
|
|
10
|
+
|
|
11
|
+
Always verify WooCommerce is installed and active before using WooCommerce functions:
|
|
12
|
+
|
|
13
|
+
```php
|
|
14
|
+
<?php
|
|
15
|
+
/**
|
|
16
|
+
* Check if WooCommerce is active
|
|
17
|
+
*/
|
|
18
|
+
function my_plugin_is_woocommerce_active() {
|
|
19
|
+
return in_array(
|
|
20
|
+
'woocommerce/woocommerce.php',
|
|
21
|
+
apply_filters( 'active_plugins', get_option( 'active_plugins' ) )
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Initialize plugin only if WooCommerce is active
|
|
27
|
+
*/
|
|
28
|
+
function my_plugin_init() {
|
|
29
|
+
if ( ! my_plugin_is_woocommerce_active() ) {
|
|
30
|
+
add_action( 'admin_notices', 'my_plugin_woocommerce_missing_notice' );
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Initialize plugin functionality
|
|
35
|
+
My_Plugin::instance();
|
|
36
|
+
}
|
|
37
|
+
add_action( 'plugins_loaded', 'my_plugin_init' );
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Display admin notice if WooCommerce is not active
|
|
41
|
+
*/
|
|
42
|
+
function my_plugin_woocommerce_missing_notice() {
|
|
43
|
+
?>
|
|
44
|
+
<div class="notice notice-error">
|
|
45
|
+
<p><?php esc_html_e( 'My Plugin requires WooCommerce to be installed and active.', 'my-plugin' ); ?></p>
|
|
46
|
+
</div>
|
|
47
|
+
<?php
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Declare WooCommerce Compatibility
|
|
52
|
+
|
|
53
|
+
```php
|
|
54
|
+
<?php
|
|
55
|
+
/**
|
|
56
|
+
* Declare HPOS (High-Performance Order Storage) compatibility
|
|
57
|
+
*/
|
|
58
|
+
add_action( 'before_woocommerce_init', function() {
|
|
59
|
+
if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
|
|
60
|
+
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
|
|
61
|
+
'custom_order_tables',
|
|
62
|
+
__FILE__,
|
|
63
|
+
true
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
} );
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Declare compatibility with WooCommerce features
|
|
70
|
+
*/
|
|
71
|
+
add_action( 'before_woocommerce_init', function() {
|
|
72
|
+
if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
|
|
73
|
+
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
|
|
74
|
+
'cart_checkout_blocks',
|
|
75
|
+
__FILE__,
|
|
76
|
+
true
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
} );
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Product Extensions
|
|
85
|
+
|
|
86
|
+
### Add Custom Product Fields
|
|
87
|
+
|
|
88
|
+
```php
|
|
89
|
+
<?php
|
|
90
|
+
/**
|
|
91
|
+
* Add custom field to product general tab
|
|
92
|
+
*/
|
|
93
|
+
function my_plugin_add_custom_product_field() {
|
|
94
|
+
woocommerce_wp_text_input( array(
|
|
95
|
+
'id' => '_custom_product_field',
|
|
96
|
+
'label' => __( 'Custom Field', 'my-plugin' ),
|
|
97
|
+
'placeholder' => __( 'Enter value', 'my-plugin' ),
|
|
98
|
+
'desc_tip' => true,
|
|
99
|
+
'description' => __( 'This is a custom field.', 'my-plugin' ),
|
|
100
|
+
) );
|
|
101
|
+
}
|
|
102
|
+
add_action( 'woocommerce_product_options_general_product_data', 'my_plugin_add_custom_product_field' );
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Save custom product field
|
|
106
|
+
*/
|
|
107
|
+
function my_plugin_save_custom_product_field( $post_id ) {
|
|
108
|
+
$custom_field = isset( $_POST['_custom_product_field'] )
|
|
109
|
+
? sanitize_text_field( $_POST['_custom_product_field'] )
|
|
110
|
+
: '';
|
|
111
|
+
|
|
112
|
+
update_post_meta( $post_id, '_custom_product_field', $custom_field );
|
|
113
|
+
}
|
|
114
|
+
add_action( 'woocommerce_process_product_meta', 'my_plugin_save_custom_product_field' );
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Display custom field on product page
|
|
118
|
+
*/
|
|
119
|
+
function my_plugin_display_custom_product_field() {
|
|
120
|
+
global $product;
|
|
121
|
+
|
|
122
|
+
$custom_field = $product->get_meta( '_custom_product_field' );
|
|
123
|
+
|
|
124
|
+
if ( $custom_field ) {
|
|
125
|
+
echo '<div class="custom-product-field">';
|
|
126
|
+
echo '<strong>' . esc_html__( 'Custom Field:', 'my-plugin' ) . '</strong> ';
|
|
127
|
+
echo esc_html( $custom_field );
|
|
128
|
+
echo '</div>';
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
add_action( 'woocommerce_single_product_summary', 'my_plugin_display_custom_product_field', 25 );
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Add Custom Product Tab
|
|
135
|
+
|
|
136
|
+
```php
|
|
137
|
+
<?php
|
|
138
|
+
/**
|
|
139
|
+
* Add custom product tab
|
|
140
|
+
*/
|
|
141
|
+
function my_plugin_add_custom_product_tab( $tabs ) {
|
|
142
|
+
$tabs['custom_tab'] = array(
|
|
143
|
+
'title' => __( 'Custom Tab', 'my-plugin' ),
|
|
144
|
+
'priority' => 50,
|
|
145
|
+
'callback' => 'my_plugin_custom_product_tab_content',
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
return $tabs;
|
|
149
|
+
}
|
|
150
|
+
add_filter( 'woocommerce_product_tabs', 'my_plugin_add_custom_product_tab' );
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Custom product tab content
|
|
154
|
+
*/
|
|
155
|
+
function my_plugin_custom_product_tab_content() {
|
|
156
|
+
global $product;
|
|
157
|
+
|
|
158
|
+
?>
|
|
159
|
+
<h2><?php esc_html_e( 'Custom Tab', 'my-plugin' ); ?></h2>
|
|
160
|
+
<p><?php esc_html_e( 'Custom tab content goes here.', 'my-plugin' ); ?></p>
|
|
161
|
+
<?php
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Cart & Checkout Extensions
|
|
168
|
+
|
|
169
|
+
### Add Custom Cart Item Data
|
|
170
|
+
|
|
171
|
+
```php
|
|
172
|
+
<?php
|
|
173
|
+
/**
|
|
174
|
+
* Add custom data to cart item
|
|
175
|
+
*/
|
|
176
|
+
function my_plugin_add_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
|
|
177
|
+
if ( isset( $_POST['custom_field'] ) ) {
|
|
178
|
+
$cart_item_data['custom_field'] = sanitize_text_field( $_POST['custom_field'] );
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return $cart_item_data;
|
|
182
|
+
}
|
|
183
|
+
add_filter( 'woocommerce_add_cart_item_data', 'my_plugin_add_cart_item_data', 10, 3 );
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Display custom cart item data
|
|
187
|
+
*/
|
|
188
|
+
function my_plugin_display_cart_item_data( $item_data, $cart_item ) {
|
|
189
|
+
if ( isset( $cart_item['custom_field'] ) ) {
|
|
190
|
+
$item_data[] = array(
|
|
191
|
+
'key' => __( 'Custom Field', 'my-plugin' ),
|
|
192
|
+
'value' => wc_clean( $cart_item['custom_field'] ),
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return $item_data;
|
|
197
|
+
}
|
|
198
|
+
add_filter( 'woocommerce_get_item_data', 'my_plugin_display_cart_item_data', 10, 2 );
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Save custom cart item data to order
|
|
202
|
+
*/
|
|
203
|
+
function my_plugin_save_order_item_meta( $item, $cart_item_key, $values, $order ) {
|
|
204
|
+
if ( isset( $values['custom_field'] ) ) {
|
|
205
|
+
$item->add_meta_data( '_custom_field', $values['custom_field'] );
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
add_action( 'woocommerce_checkout_create_order_line_item', 'my_plugin_save_order_item_meta', 10, 4 );
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Add Custom Checkout Field
|
|
212
|
+
|
|
213
|
+
```php
|
|
214
|
+
<?php
|
|
215
|
+
/**
|
|
216
|
+
* Add custom checkout field
|
|
217
|
+
*/
|
|
218
|
+
function my_plugin_add_checkout_field( $fields ) {
|
|
219
|
+
$fields['billing']['billing_custom_field'] = array(
|
|
220
|
+
'type' => 'text',
|
|
221
|
+
'label' => __( 'Custom Field', 'my-plugin' ),
|
|
222
|
+
'placeholder' => __( 'Enter value', 'my-plugin' ),
|
|
223
|
+
'required' => false,
|
|
224
|
+
'class' => array( 'form-row-wide' ),
|
|
225
|
+
'clear' => true,
|
|
226
|
+
'priority' => 100,
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
return $fields;
|
|
230
|
+
}
|
|
231
|
+
add_filter( 'woocommerce_checkout_fields', 'my_plugin_add_checkout_field' );
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Validate custom checkout field
|
|
235
|
+
*/
|
|
236
|
+
function my_plugin_validate_checkout_field() {
|
|
237
|
+
if ( isset( $_POST['billing_custom_field'] ) && empty( $_POST['billing_custom_field'] ) ) {
|
|
238
|
+
wc_add_notice(
|
|
239
|
+
__( 'Please enter a value for Custom Field.', 'my-plugin' ),
|
|
240
|
+
'error'
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
add_action( 'woocommerce_checkout_process', 'my_plugin_validate_checkout_field' );
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Save custom checkout field to order
|
|
248
|
+
*/
|
|
249
|
+
function my_plugin_save_checkout_field( $order_id ) {
|
|
250
|
+
if ( isset( $_POST['billing_custom_field'] ) ) {
|
|
251
|
+
update_post_meta(
|
|
252
|
+
$order_id,
|
|
253
|
+
'_billing_custom_field',
|
|
254
|
+
sanitize_text_field( $_POST['billing_custom_field'] )
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
add_action( 'woocommerce_checkout_update_order_meta', 'my_plugin_save_checkout_field' );
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Display custom field in order admin
|
|
262
|
+
*/
|
|
263
|
+
function my_plugin_display_order_custom_field( $order ) {
|
|
264
|
+
$custom_field = $order->get_meta( '_billing_custom_field' );
|
|
265
|
+
|
|
266
|
+
if ( $custom_field ) {
|
|
267
|
+
echo '<p><strong>' . esc_html__( 'Custom Field:', 'my-plugin' ) . '</strong> ' . esc_html( $custom_field ) . '</p>';
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
add_action( 'woocommerce_admin_order_data_after_billing_address', 'my_plugin_display_order_custom_field' );
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Order Extensions
|
|
276
|
+
|
|
277
|
+
### Add Custom Order Status
|
|
278
|
+
|
|
279
|
+
```php
|
|
280
|
+
<?php
|
|
281
|
+
/**
|
|
282
|
+
* Register custom order status
|
|
283
|
+
*/
|
|
284
|
+
function my_plugin_register_custom_order_status() {
|
|
285
|
+
register_post_status( 'wc-custom-status', array(
|
|
286
|
+
'label' => __( 'Custom Status', 'my-plugin' ),
|
|
287
|
+
'public' => true,
|
|
288
|
+
'exclude_from_search' => false,
|
|
289
|
+
'show_in_admin_all_list' => true,
|
|
290
|
+
'show_in_admin_status_list' => true,
|
|
291
|
+
'label_count' => _n_noop(
|
|
292
|
+
'Custom Status <span class="count">(%s)</span>',
|
|
293
|
+
'Custom Status <span class="count">(%s)</span>',
|
|
294
|
+
'my-plugin'
|
|
295
|
+
),
|
|
296
|
+
) );
|
|
297
|
+
}
|
|
298
|
+
add_action( 'init', 'my_plugin_register_custom_order_status' );
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Add custom status to order statuses
|
|
302
|
+
*/
|
|
303
|
+
function my_plugin_add_custom_order_status( $order_statuses ) {
|
|
304
|
+
$order_statuses['wc-custom-status'] = __( 'Custom Status', 'my-plugin' );
|
|
305
|
+
return $order_statuses;
|
|
306
|
+
}
|
|
307
|
+
add_filter( 'wc_order_statuses', 'my_plugin_add_custom_order_status' );
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Hook into Order Events
|
|
311
|
+
|
|
312
|
+
```php
|
|
313
|
+
<?php
|
|
314
|
+
/**
|
|
315
|
+
* Action when order is created
|
|
316
|
+
*/
|
|
317
|
+
function my_plugin_order_created( $order_id, $order ) {
|
|
318
|
+
// Custom logic when order is created
|
|
319
|
+
error_log( 'Order created: ' . $order_id );
|
|
320
|
+
}
|
|
321
|
+
add_action( 'woocommerce_new_order', 'my_plugin_order_created', 10, 2 );
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Action when order status changes
|
|
325
|
+
*/
|
|
326
|
+
function my_plugin_order_status_changed( $order_id, $old_status, $new_status, $order ) {
|
|
327
|
+
// Custom logic when order status changes
|
|
328
|
+
if ( 'processing' === $new_status ) {
|
|
329
|
+
// Do something when order is processing
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
add_action( 'woocommerce_order_status_changed', 'my_plugin_order_status_changed', 10, 4 );
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Action when order is completed
|
|
336
|
+
*/
|
|
337
|
+
function my_plugin_order_completed( $order_id ) {
|
|
338
|
+
$order = wc_get_order( $order_id );
|
|
339
|
+
|
|
340
|
+
// Custom logic when order is completed
|
|
341
|
+
// e.g., send to external API, update inventory, etc.
|
|
342
|
+
}
|
|
343
|
+
add_action( 'woocommerce_order_status_completed', 'my_plugin_order_completed' );
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## Payment Gateway Integration
|
|
349
|
+
|
|
350
|
+
### Create Custom Payment Gateway
|
|
351
|
+
|
|
352
|
+
```php
|
|
353
|
+
<?php
|
|
354
|
+
/**
|
|
355
|
+
* Custom Payment Gateway Class
|
|
356
|
+
*/
|
|
357
|
+
class My_Plugin_Payment_Gateway extends WC_Payment_Gateway {
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Constructor
|
|
361
|
+
*/
|
|
362
|
+
public function __construct() {
|
|
363
|
+
$this->id = 'my_custom_gateway';
|
|
364
|
+
$this->icon = '';
|
|
365
|
+
$this->has_fields = true;
|
|
366
|
+
$this->method_title = __( 'Custom Gateway', 'my-plugin' );
|
|
367
|
+
$this->method_description = __( 'Custom payment gateway description.', 'my-plugin' );
|
|
368
|
+
|
|
369
|
+
// Load settings
|
|
370
|
+
$this->init_form_fields();
|
|
371
|
+
$this->init_settings();
|
|
372
|
+
|
|
373
|
+
// Get settings
|
|
374
|
+
$this->title = $this->get_option( 'title' );
|
|
375
|
+
$this->description = $this->get_option( 'description' );
|
|
376
|
+
$this->enabled = $this->get_option( 'enabled' );
|
|
377
|
+
|
|
378
|
+
// Actions
|
|
379
|
+
add_action(
|
|
380
|
+
'woocommerce_update_options_payment_gateways_' . $this->id,
|
|
381
|
+
array( $this, 'process_admin_options' )
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Initialize gateway settings form fields
|
|
387
|
+
*/
|
|
388
|
+
public function init_form_fields() {
|
|
389
|
+
$this->form_fields = array(
|
|
390
|
+
'enabled' => array(
|
|
391
|
+
'title' => __( 'Enable/Disable', 'my-plugin' ),
|
|
392
|
+
'type' => 'checkbox',
|
|
393
|
+
'label' => __( 'Enable Custom Gateway', 'my-plugin' ),
|
|
394
|
+
'default' => 'no',
|
|
395
|
+
),
|
|
396
|
+
'title' => array(
|
|
397
|
+
'title' => __( 'Title', 'my-plugin' ),
|
|
398
|
+
'type' => 'text',
|
|
399
|
+
'description' => __( 'Payment method title shown to customers.', 'my-plugin' ),
|
|
400
|
+
'default' => __( 'Custom Payment', 'my-plugin' ),
|
|
401
|
+
'desc_tip' => true,
|
|
402
|
+
),
|
|
403
|
+
'description' => array(
|
|
404
|
+
'title' => __( 'Description', 'my-plugin' ),
|
|
405
|
+
'type' => 'textarea',
|
|
406
|
+
'description' => __( 'Payment method description shown to customers.', 'my-plugin' ),
|
|
407
|
+
'default' => __( 'Pay with custom gateway.', 'my-plugin' ),
|
|
408
|
+
'desc_tip' => true,
|
|
409
|
+
),
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Payment fields on checkout
|
|
415
|
+
*/
|
|
416
|
+
public function payment_fields() {
|
|
417
|
+
if ( $this->description ) {
|
|
418
|
+
echo wpautop( wp_kses_post( $this->description ) );
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Add custom payment fields here
|
|
422
|
+
?>
|
|
423
|
+
<fieldset>
|
|
424
|
+
<p class="form-row form-row-wide">
|
|
425
|
+
<label for="custom-field"><?php esc_html_e( 'Custom Field', 'my-plugin' ); ?></label>
|
|
426
|
+
<input type="text" id="custom-field" name="custom_field" />
|
|
427
|
+
</p>
|
|
428
|
+
</fieldset>
|
|
429
|
+
<?php
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Validate payment fields
|
|
434
|
+
*/
|
|
435
|
+
public function validate_fields() {
|
|
436
|
+
if ( empty( $_POST['custom_field'] ) ) {
|
|
437
|
+
wc_add_notice(
|
|
438
|
+
__( 'Custom field is required.', 'my-plugin' ),
|
|
439
|
+
'error'
|
|
440
|
+
);
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return true;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Process payment
|
|
449
|
+
*/
|
|
450
|
+
public function process_payment( $order_id ) {
|
|
451
|
+
$order = wc_get_order( $order_id );
|
|
452
|
+
|
|
453
|
+
// Process payment with external gateway
|
|
454
|
+
// ...
|
|
455
|
+
|
|
456
|
+
// Mark order as processing or completed
|
|
457
|
+
$order->payment_complete();
|
|
458
|
+
|
|
459
|
+
// Add order note
|
|
460
|
+
$order->add_order_note(
|
|
461
|
+
__( 'Payment completed via Custom Gateway.', 'my-plugin' )
|
|
462
|
+
);
|
|
463
|
+
|
|
464
|
+
// Reduce stock levels
|
|
465
|
+
wc_reduce_stock_levels( $order_id );
|
|
466
|
+
|
|
467
|
+
// Remove cart
|
|
468
|
+
WC()->cart->empty_cart();
|
|
469
|
+
|
|
470
|
+
// Return success
|
|
471
|
+
return array(
|
|
472
|
+
'result' => 'success',
|
|
473
|
+
'redirect' => $this->get_return_url( $order ),
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Add custom payment gateway to WooCommerce
|
|
480
|
+
*/
|
|
481
|
+
function my_plugin_add_payment_gateway( $gateways ) {
|
|
482
|
+
$gateways[] = 'My_Plugin_Payment_Gateway';
|
|
483
|
+
return $gateways;
|
|
484
|
+
}
|
|
485
|
+
add_filter( 'woocommerce_payment_gateways', 'my_plugin_add_payment_gateway' );
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
## Email Extensions
|
|
491
|
+
|
|
492
|
+
### Add Custom Email
|
|
493
|
+
|
|
494
|
+
```php
|
|
495
|
+
<?php
|
|
496
|
+
/**
|
|
497
|
+
* Custom Email Class
|
|
498
|
+
*/
|
|
499
|
+
class My_Plugin_Custom_Email extends WC_Email {
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Constructor
|
|
503
|
+
*/
|
|
504
|
+
public function __construct() {
|
|
505
|
+
$this->id = 'my_custom_email';
|
|
506
|
+
$this->title = __( 'Custom Email', 'my-plugin' );
|
|
507
|
+
$this->description = __( 'Custom email sent to customers.', 'my-plugin' );
|
|
508
|
+
$this->template_html = 'emails/custom-email.php';
|
|
509
|
+
$this->template_plain = 'emails/plain/custom-email.php';
|
|
510
|
+
$this->template_base = plugin_dir_path( __FILE__ ) . 'templates/';
|
|
511
|
+
|
|
512
|
+
// Triggers
|
|
513
|
+
add_action( 'my_plugin_custom_action', array( $this, 'trigger' ), 10, 2 );
|
|
514
|
+
|
|
515
|
+
// Call parent constructor
|
|
516
|
+
parent::__construct();
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Trigger email
|
|
521
|
+
*/
|
|
522
|
+
public function trigger( $order_id, $custom_data = null ) {
|
|
523
|
+
$this->setup_locale();
|
|
524
|
+
|
|
525
|
+
if ( $order_id ) {
|
|
526
|
+
$this->object = wc_get_order( $order_id );
|
|
527
|
+
$this->recipient = $this->object->get_billing_email();
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if ( $this->is_enabled() && $this->get_recipient() ) {
|
|
531
|
+
$this->send(
|
|
532
|
+
$this->get_recipient(),
|
|
533
|
+
$this->get_subject(),
|
|
534
|
+
$this->get_content(),
|
|
535
|
+
$this->get_headers(),
|
|
536
|
+
$this->get_attachments()
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
$this->restore_locale();
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Get email content (HTML)
|
|
545
|
+
*/
|
|
546
|
+
public function get_content_html() {
|
|
547
|
+
return wc_get_template_html(
|
|
548
|
+
$this->template_html,
|
|
549
|
+
array(
|
|
550
|
+
'order' => $this->object,
|
|
551
|
+
'email_heading' => $this->get_heading(),
|
|
552
|
+
'sent_to_admin' => false,
|
|
553
|
+
'plain_text' => false,
|
|
554
|
+
'email' => $this,
|
|
555
|
+
),
|
|
556
|
+
'',
|
|
557
|
+
$this->template_base
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* Get email content (plain text)
|
|
563
|
+
*/
|
|
564
|
+
public function get_content_plain() {
|
|
565
|
+
return wc_get_template_html(
|
|
566
|
+
$this->template_plain,
|
|
567
|
+
array(
|
|
568
|
+
'order' => $this->object,
|
|
569
|
+
'email_heading' => $this->get_heading(),
|
|
570
|
+
'sent_to_admin' => false,
|
|
571
|
+
'plain_text' => true,
|
|
572
|
+
'email' => $this,
|
|
573
|
+
),
|
|
574
|
+
'',
|
|
575
|
+
$this->template_base
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Add custom email to WooCommerce
|
|
582
|
+
*/
|
|
583
|
+
function my_plugin_add_custom_email( $emails ) {
|
|
584
|
+
$emails['My_Plugin_Custom_Email'] = new My_Plugin_Custom_Email();
|
|
585
|
+
return $emails;
|
|
586
|
+
}
|
|
587
|
+
add_filter( 'woocommerce_email_classes', 'my_plugin_add_custom_email' );
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
---
|
|
591
|
+
|
|
592
|
+
## REST API Extensions
|
|
593
|
+
|
|
594
|
+
### Add Custom REST API Endpoint
|
|
595
|
+
|
|
596
|
+
```php
|
|
597
|
+
<?php
|
|
598
|
+
/**
|
|
599
|
+
* Register custom REST API endpoint
|
|
600
|
+
*/
|
|
601
|
+
function my_plugin_register_rest_route() {
|
|
602
|
+
register_rest_route( 'my-plugin/v1', '/products/(?P<id>\d+)/custom', array(
|
|
603
|
+
'methods' => 'GET',
|
|
604
|
+
'callback' => 'my_plugin_get_product_custom_data',
|
|
605
|
+
'permission_callback' => function() {
|
|
606
|
+
return current_user_can( 'edit_posts' );
|
|
607
|
+
},
|
|
608
|
+
'args' => array(
|
|
609
|
+
'id' => array(
|
|
610
|
+
'validate_callback' => function( $param ) {
|
|
611
|
+
return is_numeric( $param );
|
|
612
|
+
},
|
|
613
|
+
),
|
|
614
|
+
),
|
|
615
|
+
) );
|
|
616
|
+
}
|
|
617
|
+
add_action( 'rest_api_init', 'my_plugin_register_rest_route' );
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Get product custom data via REST API
|
|
621
|
+
*/
|
|
622
|
+
function my_plugin_get_product_custom_data( $request ) {
|
|
623
|
+
$product_id = $request['id'];
|
|
624
|
+
$product = wc_get_product( $product_id );
|
|
625
|
+
|
|
626
|
+
if ( ! $product ) {
|
|
627
|
+
return new WP_Error( 'invalid_product', __( 'Invalid product ID.', 'my-plugin' ), array( 'status' => 404 ) );
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
return rest_ensure_response( array(
|
|
631
|
+
'id' => $product->get_id(),
|
|
632
|
+
'name' => $product->get_name(),
|
|
633
|
+
'custom_field' => $product->get_meta( '_custom_product_field' ),
|
|
634
|
+
) );
|
|
635
|
+
}
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
---
|
|
639
|
+
|
|
640
|
+
## Admin Extensions
|
|
641
|
+
|
|
642
|
+
### Add Custom Admin Column
|
|
643
|
+
|
|
644
|
+
```php
|
|
645
|
+
<?php
|
|
646
|
+
/**
|
|
647
|
+
* Add custom column to products admin
|
|
648
|
+
*/
|
|
649
|
+
function my_plugin_add_product_column( $columns ) {
|
|
650
|
+
$columns['custom_field'] = __( 'Custom Field', 'my-plugin' );
|
|
651
|
+
return $columns;
|
|
652
|
+
}
|
|
653
|
+
add_filter( 'manage_edit-product_columns', 'my_plugin_add_product_column' );
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Populate custom column
|
|
657
|
+
*/
|
|
658
|
+
function my_plugin_populate_product_column( $column, $post_id ) {
|
|
659
|
+
if ( 'custom_field' === $column ) {
|
|
660
|
+
$product = wc_get_product( $post_id );
|
|
661
|
+
$custom_field = $product->get_meta( '_custom_product_field' );
|
|
662
|
+
echo esc_html( $custom_field );
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
add_action( 'manage_product_posts_custom_column', 'my_plugin_populate_product_column', 10, 2 );
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* Make custom column sortable
|
|
669
|
+
*/
|
|
670
|
+
function my_plugin_sortable_product_column( $columns ) {
|
|
671
|
+
$columns['custom_field'] = 'custom_field';
|
|
672
|
+
return $columns;
|
|
673
|
+
}
|
|
674
|
+
add_filter( 'manage_edit-product_sortable_columns', 'my_plugin_sortable_product_column' );
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
### Add Settings Tab to WooCommerce Settings
|
|
678
|
+
|
|
679
|
+
```php
|
|
680
|
+
<?php
|
|
681
|
+
/**
|
|
682
|
+
* Add custom settings tab
|
|
683
|
+
*/
|
|
684
|
+
function my_plugin_add_settings_tab( $settings_tabs ) {
|
|
685
|
+
$settings_tabs['my_plugin'] = __( 'My Plugin', 'my-plugin' );
|
|
686
|
+
return $settings_tabs;
|
|
687
|
+
}
|
|
688
|
+
add_filter( 'woocommerce_settings_tabs_array', 'my_plugin_add_settings_tab', 50 );
|
|
689
|
+
|
|
690
|
+
/**
|
|
691
|
+
* Settings tab content
|
|
692
|
+
*/
|
|
693
|
+
function my_plugin_settings_tab_content() {
|
|
694
|
+
woocommerce_admin_fields( my_plugin_get_settings() );
|
|
695
|
+
}
|
|
696
|
+
add_action( 'woocommerce_settings_tabs_my_plugin', 'my_plugin_settings_tab_content' );
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* Save settings
|
|
700
|
+
*/
|
|
701
|
+
function my_plugin_save_settings() {
|
|
702
|
+
woocommerce_update_options( my_plugin_get_settings() );
|
|
703
|
+
}
|
|
704
|
+
add_action( 'woocommerce_update_options_my_plugin', 'my_plugin_save_settings' );
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Get settings array
|
|
708
|
+
*/
|
|
709
|
+
function my_plugin_get_settings() {
|
|
710
|
+
return array(
|
|
711
|
+
array(
|
|
712
|
+
'title' => __( 'My Plugin Settings', 'my-plugin' ),
|
|
713
|
+
'type' => 'title',
|
|
714
|
+
'id' => 'my_plugin_settings',
|
|
715
|
+
),
|
|
716
|
+
array(
|
|
717
|
+
'title' => __( 'Enable Feature', 'my-plugin' ),
|
|
718
|
+
'desc' => __( 'Enable custom feature', 'my-plugin' ),
|
|
719
|
+
'id' => 'my_plugin_enable_feature',
|
|
720
|
+
'default' => 'yes',
|
|
721
|
+
'type' => 'checkbox',
|
|
722
|
+
),
|
|
723
|
+
array(
|
|
724
|
+
'title' => __( 'Custom Option', 'my-plugin' ),
|
|
725
|
+
'desc' => __( 'Enter custom value', 'my-plugin' ),
|
|
726
|
+
'id' => 'my_plugin_custom_option',
|
|
727
|
+
'default' => '',
|
|
728
|
+
'type' => 'text',
|
|
729
|
+
'desc_tip' => true,
|
|
730
|
+
),
|
|
731
|
+
array(
|
|
732
|
+
'type' => 'sectionend',
|
|
733
|
+
'id' => 'my_plugin_settings',
|
|
734
|
+
),
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
---
|
|
740
|
+
|
|
741
|
+
## Best Practices
|
|
742
|
+
|
|
743
|
+
### DO
|
|
744
|
+
|
|
745
|
+
✅ **Check WooCommerce is active** before using WooCommerce functions
|
|
746
|
+
✅ **Declare HPOS compatibility** for modern WooCommerce versions
|
|
747
|
+
✅ **Use WooCommerce hooks and filters** instead of modifying core files
|
|
748
|
+
✅ **Sanitize all input** from forms and requests
|
|
749
|
+
✅ **Escape all output** to prevent XSS attacks
|
|
750
|
+
✅ **Use WooCommerce functions** (`wc_get_product()`, `wc_get_order()`, etc.)
|
|
751
|
+
✅ **Follow WooCommerce coding standards**
|
|
752
|
+
✅ **Test with latest WooCommerce version**
|
|
753
|
+
✅ **Use translation functions** for all user-facing text
|
|
754
|
+
✅ **Add proper error handling** for API calls and external services
|
|
755
|
+
✅ **Document custom hooks** for other developers
|
|
756
|
+
|
|
757
|
+
### DON'T
|
|
758
|
+
|
|
759
|
+
❌ **Don't modify WooCommerce core files** - use hooks and filters
|
|
760
|
+
❌ **Don't assume WooCommerce is active** - always check first
|
|
761
|
+
❌ **Don't use deprecated WooCommerce functions** - check documentation
|
|
762
|
+
❌ **Don't access database directly** - use WooCommerce CRUD classes
|
|
763
|
+
❌ **Don't ignore HPOS compatibility** - declare it explicitly
|
|
764
|
+
❌ **Don't hardcode text** - use translation functions
|
|
765
|
+
❌ **Don't skip nonce verification** on form submissions
|
|
766
|
+
❌ **Don't forget capability checks** for admin functions
|
|
767
|
+
❌ **Don't use global `$post`** - use WooCommerce objects
|
|
768
|
+
❌ **Don't break backward compatibility** without version checks
|
|
769
|
+
|
|
770
|
+
---
|
|
771
|
+
|
|
772
|
+
## Security Considerations
|
|
773
|
+
|
|
774
|
+
### Nonce Verification
|
|
775
|
+
|
|
776
|
+
```php
|
|
777
|
+
<?php
|
|
778
|
+
/**
|
|
779
|
+
* Process custom form with nonce verification
|
|
780
|
+
*/
|
|
781
|
+
function my_plugin_process_custom_form() {
|
|
782
|
+
// Verify nonce
|
|
783
|
+
if ( ! isset( $_POST['my_plugin_nonce'] ) ||
|
|
784
|
+
! wp_verify_nonce( $_POST['my_plugin_nonce'], 'my_plugin_action' ) ) {
|
|
785
|
+
wp_die( __( 'Security check failed.', 'my-plugin' ) );
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// Process form
|
|
789
|
+
$custom_field = sanitize_text_field( $_POST['custom_field'] );
|
|
790
|
+
// ...
|
|
791
|
+
}
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
### Capability Checks
|
|
795
|
+
|
|
796
|
+
```php
|
|
797
|
+
<?php
|
|
798
|
+
/**
|
|
799
|
+
* Admin action with capability check
|
|
800
|
+
*/
|
|
801
|
+
function my_plugin_admin_action() {
|
|
802
|
+
// Check user capabilities
|
|
803
|
+
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
|
804
|
+
wp_die( __( 'You do not have permission to perform this action.', 'my-plugin' ) );
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
// Perform admin action
|
|
808
|
+
// ...
|
|
809
|
+
}
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
### Data Sanitization
|
|
813
|
+
|
|
814
|
+
```php
|
|
815
|
+
<?php
|
|
816
|
+
// Text input
|
|
817
|
+
$text = sanitize_text_field( $_POST['text_field'] );
|
|
818
|
+
|
|
819
|
+
// Email
|
|
820
|
+
$email = sanitize_email( $_POST['email_field'] );
|
|
821
|
+
|
|
822
|
+
// URL
|
|
823
|
+
$url = esc_url_raw( $_POST['url_field'] );
|
|
824
|
+
|
|
825
|
+
// Integer
|
|
826
|
+
$number = absint( $_POST['number_field'] );
|
|
827
|
+
|
|
828
|
+
// Array
|
|
829
|
+
$array = array_map( 'sanitize_text_field', $_POST['array_field'] );
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
---
|
|
833
|
+
|
|
834
|
+
## Performance Optimization
|
|
835
|
+
|
|
836
|
+
### Cache Product Data
|
|
837
|
+
|
|
838
|
+
```php
|
|
839
|
+
<?php
|
|
840
|
+
/**
|
|
841
|
+
* Get product data with caching
|
|
842
|
+
*/
|
|
843
|
+
function my_plugin_get_product_data( $product_id ) {
|
|
844
|
+
$cache_key = 'my_plugin_product_' . $product_id;
|
|
845
|
+
$data = wp_cache_get( $cache_key );
|
|
846
|
+
|
|
847
|
+
if ( false === $data ) {
|
|
848
|
+
$product = wc_get_product( $product_id );
|
|
849
|
+
|
|
850
|
+
$data = array(
|
|
851
|
+
'id' => $product->get_id(),
|
|
852
|
+
'name' => $product->get_name(),
|
|
853
|
+
'price' => $product->get_price(),
|
|
854
|
+
);
|
|
855
|
+
|
|
856
|
+
wp_cache_set( $cache_key, $data, '', HOUR_IN_SECONDS );
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
return $data;
|
|
860
|
+
}
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
### Optimize Database Queries
|
|
864
|
+
|
|
865
|
+
```php
|
|
866
|
+
<?php
|
|
867
|
+
/**
|
|
868
|
+
* Get products efficiently
|
|
869
|
+
*/
|
|
870
|
+
function my_plugin_get_products() {
|
|
871
|
+
$args = array(
|
|
872
|
+
'limit' => 10,
|
|
873
|
+
'status' => 'publish',
|
|
874
|
+
'return' => 'ids', // Return only IDs for better performance
|
|
875
|
+
);
|
|
876
|
+
|
|
877
|
+
$products = wc_get_products( $args );
|
|
878
|
+
|
|
879
|
+
return $products;
|
|
880
|
+
}
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
---
|
|
884
|
+
|
|
885
|
+
## Testing
|
|
886
|
+
|
|
887
|
+
### Unit Test Example
|
|
888
|
+
|
|
889
|
+
```php
|
|
890
|
+
<?php
|
|
891
|
+
/**
|
|
892
|
+
* Test custom product field
|
|
893
|
+
*/
|
|
894
|
+
class Test_Custom_Product_Field extends WP_UnitTestCase {
|
|
895
|
+
|
|
896
|
+
public function test_save_custom_product_field() {
|
|
897
|
+
$product = WC_Helper_Product::create_simple_product();
|
|
898
|
+
|
|
899
|
+
update_post_meta( $product->get_id(), '_custom_product_field', 'test value' );
|
|
900
|
+
|
|
901
|
+
$saved_value = get_post_meta( $product->get_id(), '_custom_product_field', true );
|
|
902
|
+
|
|
903
|
+
$this->assertEquals( 'test value', $saved_value );
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
---
|
|
909
|
+
|
|
910
|
+
## Common Hooks Reference
|
|
911
|
+
|
|
912
|
+
### Product Hooks
|
|
913
|
+
|
|
914
|
+
- `woocommerce_product_options_general_product_data` - Add fields to product general tab
|
|
915
|
+
- `woocommerce_process_product_meta` - Save product meta data
|
|
916
|
+
- `woocommerce_single_product_summary` - Add content to product page
|
|
917
|
+
- `woocommerce_product_tabs` - Add/modify product tabs
|
|
918
|
+
|
|
919
|
+
### Cart Hooks
|
|
920
|
+
|
|
921
|
+
- `woocommerce_add_cart_item_data` - Add custom cart item data
|
|
922
|
+
- `woocommerce_get_item_data` - Display cart item data
|
|
923
|
+
- `woocommerce_before_calculate_totals` - Modify cart totals
|
|
924
|
+
|
|
925
|
+
### Checkout Hooks
|
|
926
|
+
|
|
927
|
+
- `woocommerce_checkout_fields` - Add/modify checkout fields
|
|
928
|
+
- `woocommerce_checkout_process` - Validate checkout fields
|
|
929
|
+
- `woocommerce_checkout_update_order_meta` - Save checkout field data
|
|
930
|
+
|
|
931
|
+
### Order Hooks
|
|
932
|
+
|
|
933
|
+
- `woocommerce_new_order` - Order created
|
|
934
|
+
- `woocommerce_order_status_changed` - Order status changed
|
|
935
|
+
- `woocommerce_order_status_completed` - Order completed
|
|
936
|
+
- `woocommerce_checkout_create_order_line_item` - Save order item meta
|
|
937
|
+
|
|
938
|
+
---
|
|
939
|
+
|
|
940
|
+
## Resources
|
|
941
|
+
|
|
942
|
+
- [WooCommerce Developer Documentation](https://woocommerce.com/document/create-a-plugin/)
|
|
943
|
+
- [WooCommerce Code Reference](https://woocommerce.github.io/code-reference/)
|
|
944
|
+
- [WooCommerce REST API](https://woocommerce.github.io/woocommerce-rest-api-docs/)
|
|
945
|
+
- [WooCommerce GitHub](https://github.com/woocommerce/woocommerce)
|
|
946
|
+
```
|
|
947
|
+
```
|
|
948
|
+
|
|
949
|
+
|