Changeset 3391617
- Timestamp:
- 11/07/2025 07:54:58 AM (3 months ago)
- Location:
- spreadr-for-woocomerce
- Files:
-
- 9 added
- 3 edited
-
tags/1.0.8 (added)
-
tags/1.0.8/includes (added)
-
tags/1.0.8/includes/class-spreadr-install.php (added)
-
tags/1.0.8/includes/class-spreadr.php (added)
-
tags/1.0.8/includes/spreadr-core-functions.php (added)
-
tags/1.0.8/includes/spreadr-frontend-functions.php (added)
-
tags/1.0.8/includes/spreadr-update-default-settings.php (added)
-
tags/1.0.8/readme.txt (added)
-
tags/1.0.8/spreadr.php (added)
-
trunk/includes/spreadr-core-functions.php (modified) (3 diffs)
-
trunk/readme.txt (modified) (1 diff)
-
trunk/spreadr.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
spreadr-for-woocomerce/trunk/includes/spreadr-core-functions.php
r3217706 r3391617 61 61 62 62 function spreadr_create_product() { 63 64 63 $allowed_ips = ['35.171.137.77']; 65 64 $remote_ip = $_SERVER['REMOTE_ADDR']; 66 65 67 66 if (!in_array($remote_ip, $allowed_ips, true)) { 68 wp_die('Forbidden ', '403 Forbidden', ['response' => 403]);67 wp_die('Forbidden Spreadr', '403 Forbidden Spreadr', ['response' => 403]); 69 68 } 70 69 … … 76 75 } 77 76 78 $product = sanitize_text_or_array_field_spreadr($_POST['product']); 79 80 $title = $product['title']; 81 $description = wp_kses_post($_POST['product']['body_html']); 82 $feature_image = $product['images'][0]; 83 $images = $product['images']; 84 85 $product_meta = $product['metafields']; 86 $product_url = $product_meta[0]['value']; 87 $tags = $product['tags']; 88 $published = $product['published']; 89 $price = $product['variants'][0]['price']; 90 $compare_price = $product['variants'][0]['compare_at_price']; 91 92 if($published == true){ 93 $published = 'publish'; 94 }else{ 95 $published = 'draft'; 96 } 97 $post_id = wp_insert_post( array( 98 'post_title' => $title, 99 'post_content' => $description, 100 'post_status' => $published, 101 'post_type' => "product", 102 ) ); 103 104 105 106 107 108 109 $thumbnail_id = spreadr_image_import($feature_image['src'],$post_id); 110 111 112 update_post_meta( $post_id, '_thumbnail_id', $thumbnail_id ); 113 114 if (count($images) > 1) { 115 array_shift($images); 116 foreach ($images as $key => $image) { 117 $image_id = spreadr_image_import($image['src'],$post_id);; 118 $product_images[] = $image_id; 119 } 120 } 121 122 123 if (!empty($product_images)) { 124 $gallery = implode(",",$product_images); 125 update_post_meta( $post_id, '_product_image_gallery', $gallery ); 126 } 127 128 129 //update_post_meta( $post_id, 'junk', json_encode($product_meta) ); 130 // 131 $producttype = 0; 132 foreach ($product_meta as $metakey => $meta) { 133 134 update_post_meta( $post_id,$meta['key'], $meta['value'] ); 135 if ($meta['key'] == 'spreadr_tags') { 136 137 $spreadtags = explode(",", $meta['value']); 138 wp_set_object_terms($post_id, $spreadtags, 'product_tag'); 139 } elseif ($meta['key'] == 'spreadr_category') { 140 141 $category_name = $meta['value']; 142 143 // Check if the category exists by name 144 $category = get_term_by( 'name', $category_name, 'product_cat' ); 145 146 if ( ! $category ) { 147 // Create the category if it doesn't exist 148 $category_id = wp_insert_term( $category_name, 'product_cat' ); 149 150 // Handle potential errors during category creation 151 if ( is_wp_error( $category_id ) ) { 152 error_log( 'Error creating category: ' . $category_id->get_error_message() ); 153 return; 154 } 155 156 // Get the term_id of the newly created category 157 $category_id = $category_id['term_id']; 158 } else { 159 // Use the existing category's term_id 160 $category_id = $category->term_id; 161 } 162 163 // Assign the category to the product 164 wp_set_object_terms( $post_id, (int) $category_id, 'product_cat', true ); 165 } 166 167 if ($meta['key'] == 'spreadr_product_button_type') { 168 169 $producttype = $meta['value']; 170 } 171 172 $meta = array(); 173 } 174 175 176 177 if($producttype == 0){ 178 wp_set_object_terms( $post_id, 'external', 'product_type' ); 77 78 // Optional but strongly recommended: CSRF check 79 if ( isset($_POST['_wpnonce']) && ! wp_verify_nonce( $_POST['_wpnonce'], 'spreadr_import' ) ) { 80 wp_send_json_error( [ 'message' => 'Invalid request (nonce failed).' ], 400 ); 81 } 82 83 // 1) Input: sanitize + validate 84 if ( empty($_POST['product']) || ! is_array($_POST['product']) ) { 85 wp_send_json_error( [ 'message' => 'Missing product payload.' ], 400 ); 86 } 87 88 $product = sanitize_text_or_array_field_spreadr( $_POST['product'] ); 89 90 $title = isset($product['title']) ? sanitize_text_field($product['title']) : ''; 91 $description = isset($_POST['product']['body_html']) ? wp_kses_post($_POST['product']['body_html']) : ''; 92 $images = isset($product['images']) && is_array($product['images']) ? $product['images'] : []; 93 $feature_img = !empty($images[0]['src']) ? esc_url_raw($images[0]['src']) : ''; 94 $metafields = isset($product['metafields']) && is_array($product['metafields']) ? $product['metafields'] : []; 95 $tags = isset($product['tags']) ? $product['tags'] : ''; // kept for backward compat if needed elsewhere 96 $is_published = !empty($product['published']) ? 'publish' : 'draft'; 97 98 $variants = isset($product['variants']) && is_array($product['variants']) ? $product['variants'] : []; 99 $first_var = !empty($variants[0]) && is_array($variants[0]) ? $variants[0] : []; 100 101 $price = isset($first_var['price']) ? wc_format_decimal($first_var['price']) : ''; 102 $compare = isset($first_var['compare_at_price']) ? wc_format_decimal($first_var['compare_at_price']) : ''; 103 104 // Extract known metafields we rely on (don’t assume order) 105 $product_url = ''; 106 $product_type = 0; // 0 = external (as per original), else simple 107 $spreadr_tags = []; 108 $category_name = ''; 109 110 foreach ( $metafields as $mf ) { 111 if ( empty($mf['key']) ) { continue; } 112 $key = sanitize_key( $mf['key'] ); 113 $val = is_scalar($mf['value']) ? wp_kses_post($mf['value']) : ''; 114 115 if ( 'spreadr_tags' === $key ) { 116 $spreadr_tags = array_filter( array_map( 'sanitize_text_field', array_map( 'trim', explode(',', $val) ) ) ); 117 } elseif ( 'spreadr_category' === $key ) { 118 $category_name = sanitize_text_field( $val ); 119 } elseif ( 'spreadr_product_button_type' === $key ) { 120 $product_type = absint( $val ); 121 } elseif ( 'product_url' === $key ) { 122 $product_url = esc_url_raw( $val ); 123 } 124 } 125 126 // Fallback: if no explicit metafield for product url but first metafield looked like it: 127 if ( ! $product_url && ! empty($metafields[0]['value']) ) { 128 $maybe_url = esc_url_raw( $metafields[0]['value'] ); 129 if ( filter_var( $maybe_url, FILTER_VALIDATE_URL ) ) { 130 $product_url = $maybe_url; 131 } 132 } 133 134 // 2) Create product post 135 if ( '' === $title ) { 136 wp_send_json_error( [ 'message' => 'Missing product title.' ], 400 ); 137 } 138 139 $post_id = wp_insert_post( [ 140 'post_title' => $title, 141 'post_content' => $description, 142 'post_status' => $is_published, 143 'post_type' => 'product', 144 ], true ); 145 146 if ( is_wp_error( $post_id ) ) { 147 wp_send_json_error( [ 'message' => 'Failed to create product.', 'error' => $post_id->get_error_message() ], 500 ); 148 } 149 150 // 3) Images 151 $gallery_ids = []; 152 153 // Feature image 154 if ( $feature_img ) { 155 $thumbnail_id = spreadr_image_import( $feature_img, $post_id ); 156 if ( $thumbnail_id && ! is_wp_error($thumbnail_id) ) { 157 update_post_meta( $post_id, '_thumbnail_id', (int) $thumbnail_id ); 158 } 159 } 160 161 // Gallery images (skip first) 162 if ( count($images) > 1 ) { 163 foreach ( array_slice($images, 1) as $img ) { 164 if ( empty($img['src']) ) { continue; } 165 $img_src = esc_url_raw( $img['src'] ); 166 $image_id = spreadr_image_import( $img_src, $post_id ); 167 if ( $image_id && ! is_wp_error($image_id) ) { 168 $gallery_ids[] = (int) $image_id; 169 } 170 } 171 if ( ! empty($gallery_ids) ) { 172 update_post_meta( $post_id, '_product_image_gallery', implode(',', $gallery_ids) ); 173 } 174 } 175 176 // 4) Metafields → post meta and taxonomy mapping 177 foreach ( $metafields as $mf ) { 178 if ( empty($mf['key']) ) { continue; } 179 $key = sanitize_key( $mf['key'] ); 180 $val = is_scalar($mf['value']) ? wp_kses_post($mf['value']) : ''; 181 update_post_meta( $post_id, $key, $val ); 182 } 183 184 // Tags 185 if ( ! empty($spreadr_tags) ) { 186 wp_set_object_terms( $post_id, $spreadr_tags, 'product_tag' ); 187 } 188 189 // Category (create if needed) 190 if ( $category_name ) { 191 $existing = get_term_by( 'name', $category_name, 'product_cat' ); 192 if ( ! $existing ) { 193 $created = wp_insert_term( $category_name, 'product_cat' ); 194 if ( is_wp_error( $created ) ) { 195 error_log( 'Spreadr: error creating category: ' . $created->get_error_message() ); 196 } else { 197 $term_id = (int) $created['term_id']; 198 wp_set_object_terms( $post_id, $term_id, 'product_cat', true ); 199 } 200 } else { 201 wp_set_object_terms( $post_id, (int) $existing->term_id, 'product_cat', true ); 202 } 203 } 204 205 // 5) Product type + stock/visibility 206 if ( (int) $product_type === 0 ) { 207 // External product 208 wp_set_object_terms( $post_id, 'external', 'product_type' ); 179 209 update_post_meta( $post_id, '_virtual', 'yes' ); 180 }else{ 181 wp_set_object_terms( $post_id, 'simple', 'product_type' ); 182 } 183 184 185 update_post_meta( $post_id, '_visibility', 'visible' ); 186 update_post_meta( $post_id, '_stock_status', 'instock'); 187 188 if($compare_price != 0) { 189 update_post_meta( $post_id, '_regular_price', $compare_price ); 190 } else { 191 update_post_meta( $post_id, '_regular_price', $price ); 192 } 193 194 update_post_meta($post_id, '_price', $price ); 195 update_post_meta($post_id, '_sale_price', $price ); 196 update_post_meta($post_id, '_backorders', 'no'); 197 update_post_meta($post_id, '_manage_stock', 'no'); 198 update_post_meta($post_id, '_product_url', $product_url); 199 200 201 $data['product_id'] = $post_id; 202 203 echo json_encode($data); 204 exit(); 205 206 } 210 } else { 211 wp_set_object_terms( $post_id, 'simple', 'product_type' ); 212 } 213 214 // WooCommerce ≥3 uses product_visibility taxonomy. 215 // Make sure it’s visible (i.e., not excluded); simplest is to clear the “exclude” terms. 216 wp_remove_object_terms( $post_id, [ 'exclude-from-catalog', 'exclude-from-search' ], 'product_visibility' ); 217 218 update_post_meta( $post_id, '_stock_status', 'instock' ); 219 update_post_meta( $post_id, '_manage_stock', 'no' ); 220 update_post_meta( $post_id, '_backorders', 'no' ); 221 222 // 6) Pricing 223 // If compare_at_price exists and is non-zero, treat it as regular price and set sale to price 224 $regular = ( '' !== $compare && (float) $compare > 0 ) ? $compare : $price; 225 $sale = $price; 226 227 if ( '' !== $regular ) { update_post_meta( $post_id, '_regular_price', $regular ); } 228 if ( '' !== $sale ) { update_post_meta( $post_id, '_sale_price', $sale ); } 229 if ( '' !== $sale ) { update_post_meta( $post_id, '_price', $sale ); } 230 231 // For external products, set button URL when available 232 if ( $product_url ) { 233 update_post_meta( $post_id, '_product_url', esc_url_raw( $product_url ) ); 234 } 235 236 // 7) Done 237 wp_send_json( [ 238 'product_id' => (int) $post_id, 239 ] ); 240 } 241 207 242 208 243 … … 212 247 213 248 function spreadr_update_product() { 214 215 $allowed_ips = ['35.171.137.77']; 216 $remote_ip = $_SERVER['REMOTE_ADDR']; 217 218 if (!in_array($remote_ip, $allowed_ips, true)) { 219 wp_die('Forbidden', '403 Forbidden', ['response' => 403]); 220 } 221 222 $api_key = $_SERVER['HTTP_X_API_KEY']; 223 $valid_key = get_option( 'spreadr_token'); 224 225 if ($api_key !== $valid_key) { 226 wp_die('Forbidden', '403 Forbidden', ['response' => 403]); 227 } 228 229 $product = sanitize_text_or_array_field_spreadr($_POST['product']); 230 $post_id = $product['product_id']; 231 $title = $product['title']; 232 $description = wp_kses_post($_POST['product']['body_html']); 233 $feature_image = $product['images'][0]; 234 $images = $product['images']; 235 236 $product_meta = $product['metafields']; 237 $product_url = $product_meta[0]['value']; 238 $tags = $product['tags']; 239 $published = $product['published']; 240 $price = $product['variants'][0]['price']; 241 $compare_price = $product['variants'][0]['compare_at_price']; 242 243 $productData = wp_update_post( array( 244 'ID' => $post_id, 245 'post_title' => $title, 246 'post_content' => $description, 247 ) 248 ); 249 250 251 252 253 254 $thumbnail_id = spreadr_image_import($feature_image['src'],$post_id); 255 256 257 update_post_meta( $post_id, '_thumbnail_id', $thumbnail_id ); 258 259 if (count($images) > 1) { 260 array_shift($images); 261 foreach ($images as $key => $image) { 262 $image_id = spreadr_image_import($image['src'],$post_id);; 263 $product_images[] = $image_id; 264 } 265 } 266 267 268 if (!empty($product_images)) { 269 $gallery = implode(",",$product_images); 270 update_post_meta( $post_id, '_product_image_gallery', $gallery ); 271 } 272 273 274 //update_post_meta( $post_id, 'junk', json_encode($product_meta) ); 275 foreach ($product_meta as $metakey => $meta) { 276 277 update_post_meta( $post_id,$meta['key'], $meta['value'] ); 278 if ($meta['key'] == 'spreadr_tags') { 279 280 $spreadtags = explode(",", $meta['value']); 281 wp_set_object_terms($post_id, $spreadtags, 'product_tag'); 282 } elseif ($meta['key'] == 'spreadr_category') { 283 284 wp_set_object_terms($post_id, $meta['value'], 'product_cat'); 285 } 286 287 $meta = array(); 288 } 289 290 291 292 wp_set_object_terms( $post_id, 'external', 'product_type' ); 293 update_post_meta( $post_id, '_visibility', 'visible' ); 294 update_post_meta( $post_id, '_stock_status', 'instock'); 295 update_post_meta( $post_id, '_virtual', 'yes' ); 296 if($compare_price != 0) { 297 update_post_meta( $post_id, '_regular_price', $compare_price ); 298 } else { 299 update_post_meta( $post_id, '_regular_price', $price ); 300 } 301 302 update_post_meta($post_id, '_price', $price ); 303 update_post_meta($post_id, '_sale_price', $price ); 304 update_post_meta($post_id, '_backorders', 'no'); 305 update_post_meta($post_id, '_manage_stock', 'no'); 306 update_post_meta($post_id, '_product_url', $product_url); 307 308 309 $data['product_id'] = $post_id; 310 311 echo json_encode($data); 312 exit(); 313 314 } 249 /* ---------- 0) AuthN & AuthZ ---------- */ 250 // Allow overriding/adding IPs via filter 251 $allowed_ips = apply_filters('spreadr_allowed_ips', ['35.171.137.77']); 252 $remote_ip = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''; 253 254 if ( ! $remote_ip || ! in_array($remote_ip, $allowed_ips, true) ) { 255 wp_die('Forbidden', '403 Forbidden', ['response' => 403]); 256 } 257 258 $api_key = isset($_SERVER['HTTP_X_API_KEY']) ? $_SERVER['HTTP_X_API_KEY'] : ''; 259 $valid_key = (string) get_option( 'spreadr_token', '' ); 260 261 // Use timing-safe comparison when possible 262 if ( empty($api_key) || empty($valid_key) || ! function_exists('hash_equals') || ! hash_equals($valid_key, $api_key) ) { 263 wp_die('Forbidden', '403 Forbidden', ['response' => 403]); 264 } 265 266 /* ---------- 1) Input validation & sanitization ---------- */ 267 if ( empty($_POST['product']) || ! is_array($_POST['product']) ) { 268 wp_send_json_error( ['message' => 'Missing product payload.'], 400 ); 269 } 270 271 $product = sanitize_text_or_array_field_spreadr( $_POST['product'] ); 272 273 $post_id = isset($product['product_id']) ? absint($product['product_id']) : 0; 274 $title = isset($product['title']) ? sanitize_text_field($product['title']) : ''; 275 $description = isset($_POST['product']['body_html']) ? wp_kses_post($_POST['product']['body_html']) : ''; 276 277 $images = isset($product['images']) && is_array($product['images']) ? $product['images'] : []; 278 $feature_img = !empty($images[0]['src']) ? esc_url_raw($images[0]['src']) : ''; 279 280 $metafields = isset($product['metafields']) && is_array($product['metafields']) ? $product['metafields'] : []; 281 282 $variants = isset($product['variants']) && is_array($product['variants']) ? $product['variants'] : []; 283 $first_var = !empty($variants[0]) && is_array($variants[0]) ? $variants[0] : []; 284 285 // Prices 286 $price = isset($first_var['price']) ? wc_format_decimal($first_var['price']) : ''; 287 $compare = isset($first_var['compare_at_price']) ? wc_format_decimal($first_var['compare_at_price']) : ''; 288 289 // Published status (optional) 290 $published = !empty($product['published']) ? 'publish' : 'draft'; 291 292 // Extract key metafields 293 $product_url = ''; 294 $product_type = 0; // 0=external, else simple (kept compatible with create function) 295 $spreadr_tags = []; 296 $category_name = ''; 297 298 foreach ( $metafields as $mf ) { 299 if ( empty($mf['key']) ) { continue; } 300 $key = sanitize_key( $mf['key'] ); 301 $val = is_scalar($mf['value']) ? wp_kses_post($mf['value']) : ''; 302 303 if ( 'spreadr_tags' === $key ) { 304 $spreadr_tags = array_filter( array_map( 'sanitize_text_field', array_map( 'trim', explode(',', $val) ) ) ); 305 } elseif ( 'spreadr_category' === $key ) { 306 $category_name = sanitize_text_field( $val ); 307 } elseif ( 'spreadr_product_button_type' === $key ) { 308 $product_type = absint( $val ); 309 } elseif ( 'product_url' === $key ) { 310 $product_url = esc_url_raw( $val ); 311 } 312 } 313 314 // Fallback if first metafield holds URL 315 if ( ! $product_url && ! empty($metafields[0]['value']) ) { 316 $maybe_url = esc_url_raw( $metafields[0]['value'] ); 317 if ( filter_var( $maybe_url, FILTER_VALIDATE_URL ) ) { 318 $product_url = $maybe_url; 319 } 320 } 321 322 if ( ! $post_id || 'product' !== get_post_type( $post_id ) ) { 323 wp_send_json_error( ['message' => 'Invalid product ID.'], 400 ); 324 } 325 326 /* ---------- 2) Update the product post ---------- */ 327 $update_args = [ 328 'ID' => $post_id, 329 'post_title' => $title ?: get_the_title($post_id), 330 'post_content' => $description, 331 ]; 332 333 // If caller sent "published" flag, honor it 334 if ( isset($product['published']) ) { 335 $update_args['post_status'] = $published; 336 } 337 338 $result = wp_update_post( $update_args, true ); 339 if ( is_wp_error( $result ) ) { 340 wp_send_json_error([ 341 'message' => 'Failed to update product.', 342 'error' => $result->get_error_message(), 343 ], 500 ); 344 } 345 346 /* ---------- 3) Images (thumbnail + gallery) ---------- */ 347 $gallery_ids = []; 348 349 // Feature image 350 if ( $feature_img ) { 351 $thumbnail_id = spreadr_image_import( $feature_img, $post_id ); 352 if ( $thumbnail_id && ! is_wp_error($thumbnail_id) ) { 353 update_post_meta( $post_id, '_thumbnail_id', (int) $thumbnail_id ); 354 } 355 } 356 357 // Gallery: rebuild from provided list (excluding the first) 358 if ( count($images) > 1 ) { 359 foreach ( array_slice($images, 1) as $img ) { 360 if ( empty($img['src']) ) { continue; } 361 $img_src = esc_url_raw( $img['src'] ); 362 $image_id = spreadr_image_import( $img_src, $post_id ); 363 if ( $image_id && ! is_wp_error($image_id) ) { 364 $gallery_ids[] = (int) $image_id; 365 } 366 } 367 } 368 369 // Update gallery meta (replace with current set) 370 update_post_meta( $post_id, '_product_image_gallery', implode(',', $gallery_ids) ); 371 372 /* ---------- 4) Metafields → post meta and taxonomies ---------- */ 373 foreach ( $metafields as $mf ) { 374 if ( empty($mf['key']) ) { continue; } 375 $key = sanitize_key( $mf['key'] ); 376 $val = is_scalar($mf['value']) ? wp_kses_post($mf['value']) : ''; 377 update_post_meta( $post_id, $key, $val ); 378 } 379 380 // Tags 381 if ( ! empty($spreadr_tags) ) { 382 wp_set_object_terms( $post_id, $spreadr_tags, 'product_tag' ); 383 } 384 385 // Category (create on the fly if needed) 386 if ( $category_name ) { 387 $existing = get_term_by( 'name', $category_name, 'product_cat' ); 388 if ( ! $existing ) { 389 $created = wp_insert_term( $category_name, 'product_cat' ); 390 if ( is_wp_error( $created ) ) { 391 error_log( 'Spreadr: error creating category during update: ' . $created->get_error_message() ); 392 } else { 393 wp_set_object_terms( $post_id, (int) $created['term_id'], 'product_cat', true ); 394 } 395 } else { 396 wp_set_object_terms( $post_id, (int) $existing->term_id, 'product_cat', true ); 397 } 398 } 399 400 /* ---------- 5) Product type, visibility, stock ---------- */ 401 if ( (int) $product_type === 0 ) { 402 // External product 403 wp_set_object_terms( $post_id, 'external', 'product_type' ); 404 update_post_meta( $post_id, '_virtual', 'yes' ); 405 } else { 406 wp_set_object_terms( $post_id, 'simple', 'product_type' ); 407 } 408 409 // Visibility: remove "exclude" terms instead of legacy _visibility 410 wp_remove_object_terms( $post_id, [ 'exclude-from-catalog', 'exclude-from-search' ], 'product_visibility' ); 411 412 update_post_meta( $post_id, '_stock_status', 'instock' ); 413 update_post_meta( $post_id, '_manage_stock', 'no' ); 414 update_post_meta( $post_id, '_backorders', 'no' ); 415 416 /* ---------- 6) Pricing ---------- */ 417 $regular = ( '' !== $compare && (float) $compare > 0 ) ? $compare : $price; 418 $sale = $price; 419 420 if ( '' !== $regular ) { update_post_meta( $post_id, '_regular_price', $regular ); } 421 if ( '' !== $sale ) { update_post_meta( $post_id, '_sale_price', $sale ); } 422 if ( '' !== $sale ) { update_post_meta( $post_id, '_price', $sale ); } 423 424 // Button URL for external 425 if ( $product_url ) { 426 update_post_meta( $post_id, '_product_url', esc_url_raw( $product_url ) ); 427 } 428 429 /* ---------- 7) Done ---------- */ 430 wp_send_json( [ 431 'product_id' => (int) $post_id, 432 ] ); 433 } 434 315 435 316 436 -
spreadr-for-woocomerce/trunk/readme.txt
r3231787 r3391617 4 4 Donate link: https://www.paypal.me/thaliatech 5 5 Requires at least: 2.9.1 6 Tested up to: 6. 7.16 Tested up to: 6.8.2 7 7 Requires PHP: 5.0 8 8 Stable tag: trunk -
spreadr-for-woocomerce/trunk/spreadr.php
r3231787 r3391617 5 5 * Plugin URI: https://spreadr.co/woocommerce 6 6 * Description: Use Spreadr Plugin to import products from Amazon to your WooCommerce store. Earn commissions via Amazon Affiliate Program or run your dropshipping business. 7 * Version: 1.0. 77 * Version: 1.0.8 8 8 * Author: spreadr 9 9 * Author URI: https://spreadr.co 10 10 * Requires at least: 4.4 11 * Tested up to: 6. 7.111 * Tested up to: 6.8.2 12 12 * WC requires at least: 2.2 13 * WC tested up to: 9.4.313 * WC tested up to: 10.3.4 14 14 * @package Spreadr 15 15 * @category Products
Note: See TracChangeset
for help on using the changeset viewer.