PluginProbe ʕ •ᴥ•ʔ
OttoKit: All-in-One Automation Platform / 1.1.36
OttoKit: All-in-One Automation Platform v1.1.36
1.1.37 1.1.36 1.1.35 1.1.34 1.1.33 1.1.32 1.1.31 1.1.30 1.1.29 1.1.28 1.1.27 1.1.9 trunk 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.20 1.0.21 1.0.22 1.0.23 1.0.24 1.0.25 1.0.26 1.0.27 1.0.28 1.0.29 1.0.30 1.0.31 1.0.32 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.38 1.0.39 1.0.40 1.0.41 1.0.42 1.0.43 1.0.44 1.0.45 1.0.46 1.0.47 1.0.48 1.0.49 1.0.50 1.0.51 1.0.52 1.0.53 1.0.54 1.0.55 1.0.56 1.0.57 1.0.58 1.0.59 1.0.60 1.0.61 1.0.62 1.0.63 1.0.64 1.0.65 1.0.66 1.0.67 1.0.68 1.0.69 1.0.7 1.0.70 1.0.71 1.0.72 1.0.73 1.0.74 1.0.75 1.0.76 1.0.77 1.0.78 1.0.79 1.0.8 1.0.80 1.0.81 1.0.82 1.0.83 1.0.84 1.0.85 1.0.86 1.0.87 1.0.88 1.0.89 1.0.9 1.0.90 1.1.0 1.1.1 1.1.10 1.1.11 1.1.12 1.1.13 1.1.14 1.1.15 1.1.16 1.1.17 1.1.18 1.1.19 1.1.2 1.1.20 1.1.21 1.1.22 1.1.23 1.1.24 1.1.25 1.1.26 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8
suretriggers / src / Integrations / woocommerce / actions / add-product-attributes.php
suretriggers / src / Integrations / woocommerce / actions Last commit date
add-attribute-terms.php 9 months ago add-customer.php 10 months ago add-emails-to-coupon.php 9 months ago add-order-note.php 11 months ago add-product-attributes.php 9 months ago add-product-to-cart.php 9 months ago add-update-order-custom-fields.php 11 months ago apply-coupon.php 9 months ago check-cart-status.php 9 months ago check-if-order-is-renewal.php 5 months ago create-attribute.php 9 months ago create-bundle-product-order.php 7 months ago create-coupon-code.php 11 months ago create-multi-product-order.php 8 months ago create-new-order.php 11 months ago create-product-variation.php 1 year ago create-product.php 1 week ago create-variable-product.php 1 week ago delete-coupon.php 1 year ago delete-customer.php 9 months ago fetch-coupon-details.php 11 months ago find-orders-by-user-id.php 11 months ago get-all-customers.php 9 months ago get-all-products.php 9 months ago get-customer-by-email.php 9 months ago get-customer-by-id.php 9 months ago get-order-details-by-order-id.php 11 months ago get-order-type-by-order-id.php 5 months ago get-orders-by-email.php 9 months ago get-product-by-id.php 1 year ago list-all-order-notes.php 9 months ago list-all-orders.php 9 months ago remove-product-from-cart.php 9 months ago retrieve-coupons-totals.php 11 months ago retrieve-customers-totals.php 11 months ago retrieve-orders-totals.php 11 months ago retrieve-products-totals.php 11 months ago retrieve-refunds-list.php 11 months ago retrieve-reviews-totals.php 11 months ago retrieve-sales-report.php 11 months ago retrieve-top-sellers-report.php 11 months ago update-product-price.php 9 months ago update-product-stock-quantity.php 9 months ago update-status-of-order.php 11 months ago
add-product-attributes.php
451 lines
1 <?php
2 /**
3 * AddProductAttributes.
4 * php version 5.6
5 *
6 * @category AddProductAttributes
7 * @package SureTriggers
8 * @author BSF <username@example.com>
9 * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3
10 * @link https://www.brainstormforce.com/
11 * @since 1.0.0
12 */
13
14 namespace SureTriggers\Integrations\Woocommerce\Actions;
15
16 use Exception;
17 use SureTriggers\Integrations\AutomateAction;
18 use SureTriggers\Traits\SingletonLoader;
19
20 /**
21 * AddProductAttributes
22 *
23 * @category AddProductAttributes
24 * @package SureTriggers
25 * @author BSF <username@example.com>
26 * @license https://www.gnu.org/licenses/gpl-3.0.html GPLv3
27 * @link https://www.brainstormforce.com/
28 * @since 1.0.0
29 */
30 class AddProductAttributes extends AutomateAction {
31
32 /**
33 * Integration type.
34 *
35 * @var string
36 */
37 public $integration = 'WooCommerce';
38
39 /**
40 * Action name.
41 *
42 * @var string
43 */
44 public $action = 'wc_add_product_attributes';
45
46 use SingletonLoader;
47
48 /**
49 * Register a action.
50 *
51 * @param array $actions actions.
52 * @return array
53 */
54 public function register( $actions ) {
55 $actions[ $this->integration ][ $this->action ] = [
56 'label' => __( 'Add Product Attributes', 'suretriggers' ),
57 'action' => 'wc_add_product_attribute',
58 'function' => [ $this, 'action_listener' ],
59 ];
60 return $actions;
61 }
62
63 /**
64 * Action listener.
65 *
66 * @param int $user_id user_id.
67 * @param int $automation_id automation_id.
68 * @param array $fields fields.
69 * @param array $selected_options selectedOptions.
70 *
71 * @return void|array|bool
72 */
73 public function _action_listener( $user_id, $automation_id, $fields, $selected_options ) {
74 if ( ! function_exists( 'WC' ) || ! function_exists( 'wc_get_product' ) ) {
75 return [
76 'status' => 'error',
77 'message' => __( 'WooCommerce not available', 'suretriggers' ),
78 ];
79 }
80
81 // Validate required fields.
82 foreach ( $fields as $field ) {
83 if ( array_key_exists( 'validationProps', $field ) && empty( $selected_options[ $field['name'] ] ) ) {
84 return [
85 'status' => 'error',
86 'message' => __( 'Required field is missing: ', 'suretriggers' ) . $field['name'],
87 ];
88 }
89 }
90
91 // Get parameters.
92 $product_id = ! empty( $selected_options['product_id'] ) ? intval( $selected_options['product_id'] ) : 0;
93 $attributes = ! empty( $selected_options['attributes'] ) ? $selected_options['attributes'] : '';
94
95 // Legacy support.
96 if ( empty( $attributes ) && ! empty( $selected_options['product_attributes'] ) ) {
97 $attributes = $selected_options['product_attributes'];
98 }
99
100 if ( empty( $product_id ) ) {
101 return [
102 'status' => 'error',
103 'message' => __( 'Product ID is required', 'suretriggers' ),
104 ];
105 }
106
107 if ( empty( $attributes ) ) {
108 return [
109 'status' => 'error',
110 'message' => __( 'Attributes are required', 'suretriggers' ),
111 ];
112 }
113
114 try {
115 // Get the product.
116 $product = wc_get_product( $product_id );
117
118 if ( ! $product instanceof \WC_Product ) {
119 return [
120 'status' => 'error',
121 'message' => __( 'Invalid product ID provided', 'suretriggers' ),
122 ];
123 }
124
125 // Get existing product attributes.
126 $existing_attributes = $product->get_attributes();
127 $updated_attributes = $existing_attributes;
128 $added_attributes = [];
129 $updated_existing = [];
130 $failed_attributes = [];
131
132 // Parse attributes input.
133 if ( is_string( $attributes ) ) {
134 // Try to decode JSON if it's a string.
135 $decoded = json_decode( $attributes, true );
136 if ( json_last_error() === JSON_ERROR_NONE ) {
137 $attributes = $decoded;
138 } else {
139 return [
140 'status' => 'error',
141 'message' => __( 'Invalid attributes format. Expected JSON array or object.', 'suretriggers' ),
142 ];
143 }
144 }
145
146 if ( ! is_array( $attributes ) ) {
147 return [
148 'status' => 'error',
149 'message' => __( 'Attributes must be an array', 'suretriggers' ),
150 ];
151 }
152
153 foreach ( $attributes as $index => $attribute_data ) {
154 // Validate attribute data structure.
155 if ( ! is_array( $attribute_data ) ) {
156 $failed_attributes[] = [
157 'data' => $attribute_data,
158 'error' => __( 'Invalid attribute data format', 'suretriggers' ),
159 ];
160 continue;
161 }
162
163 // Extract attribute information.
164 $attribute_name = ! empty( $attribute_data['name'] ) ? sanitize_text_field( $attribute_data['name'] ) : '';
165 $attribute_slug = ! empty( $attribute_data['slug'] ) ? sanitize_text_field( $attribute_data['slug'] ) : '';
166 $attribute_values = ! empty( $attribute_data['values'] ) ? $attribute_data['values'] : '';
167 $is_visible = isset( $attribute_data['visible'] ) ? (bool) $attribute_data['visible'] : false;
168 $is_variation = isset( $attribute_data['variation'] ) ? (bool) $attribute_data['variation'] : false;
169 $is_taxonomy = isset( $attribute_data['taxonomy'] ) ? (bool) $attribute_data['taxonomy'] : false;
170
171 // Legacy field support - check all possible field name variations.
172 if ( empty( $attribute_name ) && ! empty( $attribute_data['attribute'] ) ) {
173 $attribute_name = sanitize_text_field( $attribute_data['attribute'] );
174 }
175 if ( empty( $attribute_name ) && ! empty( $attribute_data['attribute_name'] ) ) {
176 $attribute_name = sanitize_text_field( $attribute_data['attribute_name'] );
177 }
178
179 if ( empty( $attribute_slug ) && ! empty( $attribute_data['attribute_slug'] ) ) {
180 $attribute_slug = sanitize_text_field( $attribute_data['attribute_slug'] );
181 }
182
183 if ( empty( $attribute_values ) && ! empty( $attribute_data['attribute_value'] ) ) {
184 $attribute_values = $attribute_data['attribute_value'];
185 }
186 if ( empty( $attribute_values ) && ! empty( $attribute_data['attribute_values'] ) ) {
187 $attribute_values = $attribute_data['attribute_values'];
188 }
189
190 // Check for other visibility field variations.
191 if ( ! isset( $attribute_data['visible'] ) && isset( $attribute_data['is_visible'] ) ) {
192 $is_visible = (bool) $attribute_data['is_visible'];
193 }
194
195 // Check for other variation field variations.
196 if ( ! isset( $attribute_data['variation'] ) && isset( $attribute_data['is_variation'] ) ) {
197 $is_variation = (bool) $attribute_data['is_variation'];
198 }
199
200 // Check for other taxonomy field variations.
201 if ( ! isset( $attribute_data['taxonomy'] ) && isset( $attribute_data['is_taxonomy'] ) ) {
202 $is_taxonomy = (bool) $attribute_data['is_taxonomy'];
203 }
204
205 if ( empty( $attribute_name ) ) {
206 $failed_attributes[] = [
207 'data' => $attribute_data,
208 'error' => __( 'Attribute name is required', 'suretriggers' ),
209 ];
210 continue;
211 }
212
213 if ( empty( $attribute_values ) ) {
214 $failed_attributes[] = [
215 'data' => $attribute_data,
216 'error' => __( 'Attribute values are required', 'suretriggers' ),
217 ];
218 continue;
219 }
220
221 // Generate slug if not provided.
222 if ( empty( $attribute_slug ) ) {
223 $attribute_slug = sanitize_title( $attribute_name );
224 }
225
226 // Prepare values array.
227 if ( is_string( $attribute_values ) ) {
228 // Try multiple separators - pipe, comma, semicolon.
229 if ( strpos( $attribute_values, '|' ) !== false ) {
230 $values_array = array_map( 'trim', explode( '|', $attribute_values ) );
231 } elseif ( strpos( $attribute_values, ',' ) !== false ) {
232 $values_array = array_map( 'trim', explode( ',', $attribute_values ) );
233 } elseif ( strpos( $attribute_values, ';' ) !== false ) {
234 $values_array = array_map( 'trim', explode( ';', $attribute_values ) );
235 } else {
236 $values_array = [ trim( $attribute_values ) ];
237 }
238 } elseif ( is_array( $attribute_values ) ) {
239 $values_array = array_map( 'trim', $attribute_values );
240 } else {
241 $values_array = [ trim( $attribute_values ) ];
242 }
243
244 // Remove empty values.
245 $values_array = array_filter(
246 $values_array,
247 function( $value ) {
248 return ! empty( $value );
249 }
250 );
251
252 if ( empty( $values_array ) ) {
253 $failed_attributes[] = [
254 'data' => $attribute_data,
255 'error' => __( 'No valid attribute values provided', 'suretriggers' ),
256 ];
257 continue;
258 }
259
260 try {
261 $attribute_key = sanitize_title( $attribute_name );
262 $taxonomy_name = '';
263 if ( $is_taxonomy ) {
264 // Handle taxonomy-based attributes.
265
266 // Check if it's a global attribute.
267 if ( strpos( $attribute_slug, 'pa_' ) === 0 ) {
268 $taxonomy_name = $attribute_slug;
269 } else {
270 $taxonomy_name = 'pa_' . $attribute_slug;
271 }
272
273 // Ensure taxonomy exists - create if it doesn't exist.
274 if ( ! taxonomy_exists( $taxonomy_name ) ) {
275
276 // First create the attribute in WooCommerce.
277 $attribute_args = [
278 'name' => $attribute_name,
279 'slug' => str_replace( 'pa_', '', $taxonomy_name ),
280 'type' => 'select',
281 'order_by' => 'menu_order',
282 'has_archives' => false,
283 ];
284
285 $attribute_id = wc_create_attribute( $attribute_args );
286
287 if ( is_wp_error( $attribute_id ) ) {
288 $failed_attributes[] = [
289 'data' => $attribute_data,
290 'error' => sprintf( __( 'Failed to create attribute: %s', 'suretriggers' ), $attribute_id->get_error_message() ),
291 ];
292 continue;
293 }
294
295 // Register the taxonomy.
296 register_taxonomy(
297 $taxonomy_name,
298 'product',
299 [
300 'labels' => [
301 'name' => $attribute_name,
302 ],
303 'hierarchical' => false,
304 'public' => false,
305 'show_ui' => false,
306 'query_var' => true,
307 'rewrite' => false,
308 ]
309 );
310 }
311
312 // Set terms for the product.
313 $term_ids = [];
314 foreach ( $values_array as $value ) {
315 $term = get_term_by( 'name', $value, $taxonomy_name );
316 if ( ! $term ) {
317 // Try to create the term if it doesn't exist.
318 $term_result = wp_insert_term( $value, $taxonomy_name );
319 if ( ! is_wp_error( $term_result ) ) {
320 $term_ids[] = $term_result['term_id'];
321 }
322 } else {
323 $term_ids[] = $term->term_id;
324 }
325 }
326
327 if ( ! empty( $term_ids ) ) {
328 wp_set_object_terms( $product_id, $term_ids, $taxonomy_name );
329 }
330
331 // Create WC_Product_Attribute object.
332 $attribute_object = new \WC_Product_Attribute();
333 $attribute_object->set_name( $taxonomy_name );
334 $attribute_object->set_options( $term_ids );
335 $attribute_object->set_visible( $is_visible );
336 $attribute_object->set_variation( $is_variation );
337
338 $updated_attributes[ $taxonomy_name ] = $attribute_object;
339
340 } else {
341 // Handle custom (non-taxonomy) attributes.
342
343 // Create WC_Product_Attribute object.
344 $attribute_object = new \WC_Product_Attribute();
345 $attribute_object->set_name( $attribute_name );
346 $attribute_object->set_options( $values_array );
347 $attribute_object->set_visible( $is_visible );
348 $attribute_object->set_variation( $is_variation );
349
350 $updated_attributes[ $attribute_key ] = $attribute_object;
351 }
352
353 // Track what was added/updated.
354 if ( isset( $existing_attributes[ $is_taxonomy ? $taxonomy_name : $attribute_key ] ) ) {
355 $updated_existing[] = [
356 'name' => $attribute_name,
357 'slug' => $is_taxonomy ? $taxonomy_name : $attribute_key,
358 'values' => $values_array,
359 'is_taxonomy' => $is_taxonomy,
360 'visible' => $is_visible,
361 'variation' => $is_variation,
362 ];
363 } else {
364 $added_attributes[] = [
365 'name' => $attribute_name,
366 'slug' => $is_taxonomy ? $taxonomy_name : $attribute_key,
367 'values' => $values_array,
368 'is_taxonomy' => $is_taxonomy,
369 'visible' => $is_visible,
370 'variation' => $is_variation,
371 ];
372 }
373 } catch ( Exception $e ) {
374 $failed_attributes[] = [
375 'data' => $attribute_data,
376 'error' => $e->getMessage(),
377 ];
378 }
379 }
380
381 // Update product attributes.
382 $product->set_attributes( $updated_attributes );
383 $product->save();
384
385 // Clear caches.
386 wc_delete_product_transients( $product_id );
387 wp_cache_delete( 'wc_product_' . $product_id, 'products' );
388
389 // Get updated product data.
390 $product = wc_get_product( $product_id ); // Refresh product data.
391 if ( ! $product ) {
392 return [
393 'status' => 'error',
394 'message' => __( 'Failed to retrieve updated product', 'suretriggers' ),
395 ];
396 }
397 $final_attributes = $product->get_attributes();
398
399 $formatted_attributes = [];
400 foreach ( $final_attributes as $key => $attribute ) {
401 if ( $attribute instanceof \WC_Product_Attribute ) {
402 $formatted_attributes[] = [
403 'name' => $attribute->get_name(),
404 'slug' => $key,
405 'values' => $attribute->get_options(),
406 'is_taxonomy' => $attribute->is_taxonomy(),
407 'visible' => $attribute->get_visible(),
408 'variation' => $attribute->get_variation(),
409 ];
410 }
411 }
412
413 $response = [
414 'status' => 'success',
415 'message' => sprintf(
416 __( 'Processed %1$d attributes: %2$d added, %3$d updated, %4$d failed', 'suretriggers' ),
417 count( $attributes ),
418 count( $added_attributes ),
419 count( $updated_existing ),
420 count( $failed_attributes )
421 ),
422 'product_id' => $product_id,
423 'product_name' => $product->get_name(),
424 'product_type' => $product->get_type(),
425 'added_attributes' => $added_attributes,
426 'updated_attributes' => $updated_existing,
427 'failed_attributes' => $failed_attributes,
428 'all_attributes' => $formatted_attributes,
429 'attributes_count' => count( $formatted_attributes ),
430 'summary' => [
431 'total_processed' => count( $attributes ),
432 'added' => count( $added_attributes ),
433 'updated' => count( $updated_existing ),
434 'failed' => count( $failed_attributes ),
435 'final_count' => count( $formatted_attributes ),
436 ],
437 ];
438
439 return $response;
440
441 } catch ( Exception $e ) {
442 return [
443 'status' => 'error',
444 'message' => __( 'Error adding product attributes: ', 'suretriggers' ) . $e->getMessage(),
445 ];
446 }
447 }
448 }
449
450 AddProductAttributes::get_instance();
451