Product Feed PRO for WooCommerce - Version 3.0.0

Version Description

Bug fix for include_only filters

Download this release

Release Info

Developer jorisverwater
Plugin Icon 128x128 Product Feed PRO for WooCommerce
Version 3.0.0
Comparing to
See all releases

Code changes from version 2.0.0 to 3.0.0

TODO.txt CHANGED
@@ -1,25 +1,32 @@
1
  So you found my to-do list for future features in this plugin? Well, hope you enjoy the little sneak preview of what's coming. Missing some features you might like? Drop me a line at support@adtribes.io and we might just add it to the list. Thanks!
2
 
3
- Upcoming releases:
4
- - Fix attribute mapping page
5
- - Fix too large POST requests (sites with > 200 categories)
6
- - Tracking & conversion
7
- - dynamic dropdowns in GA / tracking page for values
8
- - Add support for Composite products: https://woocommerce.com/products/composite-products/
9
- - Add support for Bundled products: https://woocommerce.com/products/product-bundles/
10
- - Add WPML support
11
- - Blinking processing should update without refreshing
12
- - Support Amazon templates
13
- - Add possibility to copy/clone projects
14
 
15
- Later:
16
- - Add Category-path attribute (Trovaprezzi)
17
- - Make it possible to drag and drop filters and rules in a specific order of execution
18
- - Add Spinner to Bootstrap typeahead autosuggest
19
- - Regular expression usage in category mapping and feed rules and filter settings
20
- - Cron interval configurable for user (exact timing instead of just daily,twicedaily or hourly)
21
- - Tabbed configuration of feed
22
- - Add localisation (at least for nl_NL and nl_BE / fr_BE) - https://codex.wordpress.org/I18n_for_WordPress_Developers#Translating_Plugins_and_Themes
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
  DESIGN ISSUES:
25
- - new unique grey menu icons for wordpress
1
  So you found my to-do list for future features in this plugin? Well, hope you enjoy the little sneak preview of what's coming. Missing some features you might like? Drop me a line at support@adtribes.io and we might just add it to the list. Thanks!
2
 
3
+ ELITE TO DO:
4
+ - toevoegen utm parameters aan alle linkjes in de plugin
5
+ - notificaties zijn dismisable, maar na een tijdje moeten ze toch weer tonen voor de licentie gebruikers. Hoe gaan we dat doen?
6
+
 
 
 
 
 
 
 
7
 
8
+ MOST URGENT ISSUES:
9
+ 1. Fix step between page 0 en 1 for shops that have a lot of attributes. Why is it running into memory issues? Building of drop-downs full of attributes, can it be done with one call?
10
+ 2. Fix status update blinking percentage
11
+
12
+ TO-DO:
13
+ 4. add WPML support
14
+ 5. X en + operators toevoegen aan de rules zodat je prijs x 1.2 kan doen of prijs + 5 euro
15
+ 6. do not immediatly start generating the product feed after final step of configuration as it might run into a timeout
16
+ 7. attribute mapping werkt niet als er teveel attributen zijn. Pagina sneller maken!
17
+ 8. Tracking & conversion
18
+ - dynamic dropdowns in GA / tracking page for values
19
+ 9. Add support for Composite products: https://woocommerce.com/products/composite-products/
20
+ 10. Add support for Bundled products: https://woocommerce.com/products/product-bundles/
21
+ 11. Add and option to create rules with formula's in them
22
+ 12. Add more complex rules based on more than just 1 condition (AND)
23
+ 13. Support Amazon templates
24
+ 14. Add possibility to copy/clone projects
25
+ 15. Add a link to 'visit page' on plugin section page
26
+ 17. Regular expression usage in category mapping and feed rules and filter settings
27
+ 18. Cron interval configurable for user (exact timing instead of just daily,twicedaily or hourly)
28
+ 19. Tabbed configuration of feed
29
+ 20. Add localisation (at least for nl_NL and nl_BE / fr_BE) - https://codex.wordpress.org/I18n_for_WordPress_Developers#Translating_Plugins_and_Themes
30
 
31
  DESIGN ISSUES:
32
+ 21. new unique grey menu icons for wordpress
classes/channels/class-beslist.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Settings for Beslist feeds
4
+ */
5
+ class WooSEA_beslist {
6
+ public $beslist;
7
+
8
+ public static function get_channel_attributes() {
9
+
10
+ $sitename = get_option('blogname');
11
+
12
+ $beslist = array(
13
+ "Feed fields" => array(
14
+ "Title" => array(
15
+ "name" => "title",
16
+ "feed_name" => "title",
17
+ "format" => "required",
18
+ "woo_suggest" => "title",
19
+ ),
20
+ "Price" => array(
21
+ "name" => "price",
22
+ "feed_name" => "price",
23
+ "format" => "required",
24
+ "woo_suggest" => "price",
25
+ ),
26
+ "Unique code" => array(
27
+ "name" => "unique_code",
28
+ "feed_name" => "unique_code",
29
+ "format" => "required",
30
+ "woo_suggest" => "id",
31
+ ),
32
+ "Product URL" => array(
33
+ "name" => "product_url",
34
+ "feed_name" => "product_url",
35
+ "format" => "required",
36
+ "woo_suggest" => "link",
37
+ ),
38
+ "Image URL" => array(
39
+ "name" => "image_url",
40
+ "feed_name" => "image_url",
41
+ "format" => "required",
42
+ "woo_suggest" => "image",
43
+ ),
44
+ "Extra image 1" => array(
45
+ "name" => "extra_image_1",
46
+ "feed_name" => "extra_image_1",
47
+ "format" => "optional",
48
+ ),
49
+ "Extra image 2" => array(
50
+ "name" => "extra_image_2",
51
+ "feed_name" => "extra_image_2",
52
+ "format" => "optional",
53
+ ),
54
+ "Extra image 3" => array(
55
+ "name" => "extra_image_3",
56
+ "feed_name" => "extra_image_3",
57
+ "format" => "optional",
58
+ ),
59
+ "Category" => array(
60
+ "name" => "category",
61
+ "feed_name" => "category",
62
+ "format" => "required",
63
+ "woo_suggest" => "category_path",
64
+ ),
65
+ "Delivery period" => array(
66
+ "name" => "delivery_period",
67
+ "feed_name" => "delivery_period",
68
+ "format" => "required",
69
+ "woo_suggest" => "",
70
+ ),
71
+ "Delivery charges" => array(
72
+ "name" => "delivery_charges",
73
+ "feed_name" => "delivery_charges",
74
+ "format" => "required",
75
+ ),
76
+ "EAN" => array(
77
+ "name" => "EAN",
78
+ "feed_name" => "EAN",
79
+ "format" => "required",
80
+ ),
81
+ "Product description" => array(
82
+ "name" => "description",
83
+ "feed_name" => "description",
84
+ "format" => "required",
85
+ "woo_suggest" => "description",
86
+ ),
87
+ "Display" => array(
88
+ "name" => "display",
89
+ "feed_name" => "display",
90
+ "format" => "optional",
91
+ ),
92
+ "SKU" => array(
93
+ "name" => "SKU",
94
+ "feed_name" => "SKU",
95
+ "format" => "optional",
96
+ ),
97
+ "Brand" => array(
98
+ "name" => "Brand",
99
+ "feed_name" => "brand",
100
+ "format" => "optional",
101
+ ),
102
+ "Size" => array(
103
+ "name" => "size",
104
+ "feed_name" => "size",
105
+ "format" => "optional",
106
+ ),
107
+ "Condition" => array(
108
+ "name" => "condition",
109
+ "feed_name" => "condition",
110
+ "format" => "optional",
111
+ "woo_suggest" => "condition",
112
+ ),
113
+ "Variant code" => array(
114
+ "name" => "variant_code",
115
+ "feed_name" => "variant_code",
116
+ "format" => "optional",
117
+ ),
118
+ "Model code" => array(
119
+ "name" => "model_code",
120
+ "feed_name" => "model_code",
121
+ "format" => "optional",
122
+ ),
123
+ "Old price" => array(
124
+ "name" => "old_price",
125
+ "feed_name" => "old_price",
126
+ "format" => "optional",
127
+ ),
128
+ ),
129
+ );
130
+ return $beslist;
131
+ }
132
+ }
133
+ ?>
classes/channels/class-google_shopping.php CHANGED
@@ -84,6 +84,7 @@ class WooSEA_google_shopping {
84
  "name" => "sale_price_effective_date",
85
  "feed_name" => "g:sale_price_effective_date",
86
  "format" => "optional",
 
87
  ),
88
  "Unit pricing measure" => array(
89
  "name" => "unit_pricing_measure",
@@ -91,8 +92,8 @@ class WooSEA_google_shopping {
91
  "format" => "optional",
92
  ),
93
  "Unit pricing base measure" => array(
94
- "name" => "unit_pricing_measure",
95
- "feed_name" => "g:unit_pricing_measure",
96
  "format" => "optional",
97
  ),
98
  "Installment" => array(
84
  "name" => "sale_price_effective_date",
85
  "feed_name" => "g:sale_price_effective_date",
86
  "format" => "optional",
87
+ "woo_suggest" => "sale_price_effective_date",
88
  ),
89
  "Unit pricing measure" => array(
90
  "name" => "unit_pricing_measure",
92
  "format" => "optional",
93
  ),
94
  "Unit pricing base measure" => array(
95
+ "name" => "unit_pricing_base_measure",
96
+ "feed_name" => "g:unit_pricing_base_measure",
97
  "format" => "optional",
98
  ),
99
  "Installment" => array(
classes/channels/class-google_shopping_promotions.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Settings for Google Shopping Promotions feeds
4
+ */
5
+ class WooSEA_google_shopping_promotions {
6
+ public $google_attributes_promotions;
7
+
8
+ public static function get_channel_attributes() {
9
+ $sitename = get_option('blogname');
10
+
11
+ $google_attributes_promotions = array(
12
+ "Feed fields" => array(
13
+ "promotion_id" => array(
14
+ "name" => "promotion_id",
15
+ "feed_name" => "promotion_id",
16
+ "format" => "required",
17
+ ),
18
+ "product_applicability" => array(
19
+ "name" => "product_applicability",
20
+ "feed_name" => "product_applicability",
21
+ "format" => "required",
22
+ ),
23
+ "offer_type" => array(
24
+ "name" => "offer_type",
25
+ "feed_name" => "offer_type",
26
+ "format" => "required",
27
+ ),
28
+ "long_title" => array(
29
+ "name" => "long_title",
30
+ "feed_name" => "long_title",
31
+ "format" => "required",
32
+ ),
33
+ "promotion_effective_dates" => array(
34
+ "name" => "promotion_effective_dates",
35
+ "feed_name" => "promotion_effective_dates",
36
+ "format" => "required",
37
+ ),
38
+ "redemption_channel" => array(
39
+ "name" => "redemption_channel",
40
+ "feed_name" => "redemption_channel",
41
+ "format" => "required",
42
+ ),
43
+ "promotional_display_dates" => array(
44
+ "name" => "promotional_display_dates",
45
+ "feed_name" => "promotional_display_dates",
46
+ "format" => "optional",
47
+ ),
48
+ "minimum_purchase_amount" => array(
49
+ "name" => "minimum_purchase_amount",
50
+ "feed_name" => "minimum_purchase_amount",
51
+ "format" => "optional",
52
+ ),
53
+ "generic_redemption_code" => array(
54
+ "name" => "generic_redemption_code",
55
+ "feed_name" => "generic_redemption_code",
56
+ "format" => "optional",
57
+ ),
58
+ ),
59
+ "Structured data attributes" => array(
60
+ "percent_off" => array(
61
+ "name" => "percent_off",
62
+ "feed_name" => "percent_off",
63
+ "format" => "optional",
64
+ ),
65
+ "money_off_amount" => array(
66
+ "name" => "percent_off_amount",
67
+ "feed_name" => "percent_off_amount",
68
+ "format" => "optional",
69
+ ),
70
+ "buy_this_quantity" => array(
71
+ "name" => "buy_this_quantity",
72
+ "feed_name" => "buy_this_quantity",
73
+ "format" => "optional",
74
+ ),
75
+ "get_this_quantity_discounted" => array(
76
+ "name" => "get_this_quantity_discounted",
77
+ "feed_name" => "get_this_quantity_discounted",
78
+ "format" => "optional",
79
+ ),
80
+ "free_shipping" => array(
81
+ "name" => "free_shipping",
82
+ "feed_name" => "free_shipping",
83
+ "format" => "optional",
84
+ ),
85
+ "free_gift_value" => array(
86
+ "name" => "free_gift_value",
87
+ "feed_name" => "free_gift_value",
88
+ "format" => "optional",
89
+ ),
90
+ "free_gift_description" => array(
91
+ "name" => "free_gift_description",
92
+ "feed_name" => "free_gift_description",
93
+ "format" => "optional",
94
+ ),
95
+ "free_gift_item_id" => array(
96
+ "name" => "free_gift_item_id",
97
+ "feed_name" => "free_gift_item_id",
98
+ "format" => "optional",
99
+ ),
100
+ ),
101
+ );
102
+ return $google_attributes_promotions;
103
+ }
104
+ }
105
+ ?>
classes/channels/class-kijiji.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Settings for Kijiji Italy feeds
4
+ */
5
+ class WooSEA_kijiji {
6
+ public $kijiji;
7
+
8
+ public static function get_channel_attributes() {
9
+ $sitename = get_option('blogname');
10
+
11
+ $kijiji = array(
12
+ "Feed fields" => array(
13
+ "PartnerId" => array(
14
+ "name" => "PartnerId",
15
+ "feed_name" => "PartnerId",
16
+ "format" => "required",
17
+ "woo_suggest" => "id",
18
+ ),
19
+ "Action" => array(
20
+ "name" => "Action",
21
+ "feed_name" => "Action",
22
+ "format" => "required",
23
+ ),
24
+ "Title" => array(
25
+ "name" => "Title",
26
+ "feed_name" => "Title",
27
+ "format" => "required",
28
+ "woo_suggest" => "title",
29
+ ),
30
+ "Description" => array(
31
+ "name" => "Description",
32
+ "feed_name" => "Description",
33
+ "format" => "required",
34
+ "woo_suggest" => "description",
35
+ ),
36
+ "E-mail" => array(
37
+ "name" => "E-mail",
38
+ "feed_name" => "Email",
39
+ "format" => "required",
40
+ ),
41
+ "URL" => array(
42
+ "name" => "URL",
43
+ "feed_name" => "URL",
44
+ "format" => "required",
45
+ "woo_suggest" => "link",
46
+ ),
47
+ "Price" => array(
48
+ "name" => "Price",
49
+ "feed_name" => "Price",
50
+ "format" => "required",
51
+ "woo_suggest" => "price",
52
+ ),
53
+ "Tipo Prezzo" => array(
54
+ "name" => "Tipo Prezzo",
55
+ "feed_name" => "Tipo Prezzo",
56
+ "format" => "optional",
57
+ ),
58
+ "Municipality code" => array(
59
+ "name" => "Municipality code",
60
+ "feed_name" => "Municipality code",
61
+ "format" => "optional",
62
+ ),
63
+ "Category" => array(
64
+ "name" => "Category",
65
+ "feed_name" => "Category",
66
+ "format" => "required",
67
+ "woo_suggest" => "categories",
68
+ ),
69
+ "Seller type" => array(
70
+ "name" => "Seller type",
71
+ "feed_name" => "Seller type",
72
+ "format" => "optional",
73
+ ),
74
+ "Publication date" => array(
75
+ "name" => "Publication date",
76
+ "feed_name" => "Publication date",
77
+ "format" => "required",
78
+ "woo_suggest" => "publication_date",
79
+ ),
80
+ "Pic 1" => array(
81
+ "name" => "Pic 1",
82
+ "feed_name" => "Pic 1",
83
+ "format" => "optional",
84
+ ),
85
+ "Pic 2" => array(
86
+ "name" => "Pic 2",
87
+ "feed_name" => "Pic 2",
88
+ "format" => "optional",
89
+ ),
90
+ "Pic 3" => array(
91
+ "name" => "Pic 3",
92
+ "feed_name" => "Pic 3",
93
+ "format" => "optional",
94
+ ),
95
+ "Pic 4" => array(
96
+ "name" => "Pic 4",
97
+ "feed_name" => "Pic 4",
98
+ "format" => "optional",
99
+ ),
100
+ "Pic 5" => array(
101
+ "name" => "Pic 5",
102
+ "feed_name" => "Pic 5",
103
+ "format" => "optional",
104
+ ),
105
+ "Pic 6" => array(
106
+ "name" => "Pic 6",
107
+ "feed_name" => "Pic 6",
108
+ "format" => "optional",
109
+ ),
110
+ "Pic 7" => array(
111
+ "name" => "Pic 7",
112
+ "feed_name" => "Pic 7",
113
+ "format" => "optional",
114
+ ),
115
+ "Pic 8" => array(
116
+ "name" => "Pic 8",
117
+ "feed_name" => "Pic 8",
118
+ "format" => "optional",
119
+ ),
120
+ "Pic 9" => array(
121
+ "name" => "Pic 9",
122
+ "feed_name" => "Pic 9",
123
+ "format" => "optional",
124
+ ),
125
+ ),
126
+ );
127
+ return $kijiji;
128
+ }
129
+ }
130
+ ?>
classes/channels/class-manomano.php ADDED
@@ -0,0 +1,270 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Settings for ManoMano.co.uk feeds
4
+ */
5
+ class WooSEA_manomano {
6
+ public $manomano;
7
+
8
+ public static function get_channel_attributes() {
9
+
10
+ $sitename = get_option('blogname');
11
+
12
+ $manomano = array(
13
+ "Feed fields" => array(
14
+ "SKU" => array(
15
+ "name" => "sku",
16
+ "feed_name" => "sku",
17
+ "format" => "required",
18
+ "woo_suggest" => "id",
19
+ ),
20
+ "SKU Manufacturer" => array(
21
+ "name" => "sku manufacturer",
22
+ "feed_name" => "sku_manufacturer",
23
+ "format" => "required",
24
+ ),
25
+ "EAN" => array(
26
+ "name" => "ean",
27
+ "feed_name" => "ean",
28
+ "format" => "required",
29
+ ),
30
+ "title" => array(
31
+ "name" => "title",
32
+ "feed_name" => "title",
33
+ "format" => "required",
34
+ "woo_suggest" => "title",
35
+ ),
36
+ "description" => array(
37
+ "name" => "description",
38
+ "feed_name" => "description",
39
+ "format" => "required",
40
+ "woo_suggest" => "description",
41
+ ),
42
+ "Product price vat inc" => array(
43
+ "name" => "product price vat inc",
44
+ "feed_name" => "product_price_vat_inc",
45
+ "format" => "required",
46
+ "woo_suggest" => "price",
47
+ ),
48
+ "Shipping price vat inc" => array(
49
+ "name" => "shipping price vat inc",
50
+ "feed_name" => "shipping_price_vat_inc",
51
+ "format" => "required",
52
+ ),
53
+ "Quantity" => array(
54
+ "name" => "quantity",
55
+ "feed_name" => "quantity",
56
+ "format" => "required",
57
+ ),
58
+ "Brand" => array(
59
+ "name" => "brand",
60
+ "feed_name" => "brand",
61
+ "format" => "required",
62
+ ),
63
+ "Merchant category" => array(
64
+ "name" => "merchant category",
65
+ "feed_name" => "merchant_category",
66
+ "format" => "required",
67
+ ),
68
+ "Product URL" => array(
69
+ "name" => "product url",
70
+ "feed_name" => "product_url",
71
+ "format" => "required",
72
+ "woo_suggest" => "link",
73
+ ),
74
+ "Image 1" => array(
75
+ "name" => "image 1",
76
+ "feed_name" => "image_1",
77
+ "format" => "required",
78
+ "woo_suggest" => "image",
79
+ ),
80
+ "Image 2" => array(
81
+ "name" => "image 2",
82
+ "feed_name" => "image_2",
83
+ "format" => "optional",
84
+ ),
85
+ "Image 3" => array(
86
+ "name" => "image 3",
87
+ "feed_name" => "image_3",
88
+ "format" => "optional",
89
+ ),
90
+ "Image 4" => array(
91
+ "name" => "image 4",
92
+ "feed_name" => "image_4",
93
+ "format" => "optional",
94
+ ),
95
+ "Image 5" => array(
96
+ "name" => "image 5",
97
+ "feed_name" => "image_5",
98
+ "format" => "optional",
99
+ ),
100
+ "Retail price vat inc" => array(
101
+ "name" => "retail price vat inc",
102
+ "feed_name" => "retail_price_vat_inc",
103
+ "format" => "optional",
104
+ ),
105
+ "Product vat rate" => array(
106
+ "name" => "product vat rate",
107
+ "feed_name" => "product_vat_rate",
108
+ "format" => "optional",
109
+ ),
110
+ "Shipping vat rate" => array(
111
+ "name" => "shipping vat rate",
112
+ "feed_name" => "shipping_vat_rate",
113
+ "format" => "optional",
114
+ ),
115
+ "Manufacturer PDF" => array(
116
+ "name" => "manufacturer pdf",
117
+ "feed_name" => "manufacturer_pdf",
118
+ "format" => "optional",
119
+ ),
120
+ "ParentSKU" => array(
121
+ "name" => "parentSKU",
122
+ "feed_name" => "ParentSKU",
123
+ "format" => "optional",
124
+ ),
125
+ "Cross Sell SKU" => array(
126
+ "name" => "Cross Sell SKU",
127
+ "feed_name" => "Cross_Sell_SKU",
128
+ "format" => "optional",
129
+ ),
130
+ "ManufacturerWarrantyTime" => array(
131
+ "name" => "ManufacturerWarrantyTime",
132
+ "feed_name" => "ManufacturerWarrantyTime",
133
+ "format" => "optional",
134
+ ),
135
+ "Carrier" => array(
136
+ "name" => "Carrier",
137
+ "feed_name" => "carrier",
138
+ "format" => "required",
139
+ ),
140
+ "Shipping Time" => array(
141
+ "name" => "Shipping Time",
142
+ "feed_name" => "shipping_time",
143
+ "format" => "required",
144
+ ),
145
+ "Use Grid" => array(
146
+ "name" => "Use Grid",
147
+ "feed_name" => "use_grid",
148
+ "format" => "required",
149
+ ),
150
+ "Carrier Grid 1" => array(
151
+ "name" => "Carrier Grid 1",
152
+ "feed_name" => "carrier_grid_1",
153
+ "format" => "required",
154
+ ),
155
+ "Shipping time carrier grid 1" => array(
156
+ "name" => "Shipping time carrier grid 1",
157
+ "feed_name" => "shipping_time_carrier_grid_1",
158
+ "format" => "required",
159
+ ),
160
+ "DisplayWeight" => array(
161
+ "name" => "DisplayWeight",
162
+ "feed_name" => "DisplayWeight",
163
+ "format" => "required",
164
+ ),
165
+ "Carrier Grid 2" => array(
166
+ "name" => "Carrier Grid 2",
167
+ "feed_name" => "carrier_grid_2",
168
+ "format" => "optional",
169
+ ),
170
+ "Shipping time carrier grid 2" => array(
171
+ "name" => "Shipping time carrier grid 2",
172
+ "feed_name" => "shipping_time_carrier_grid_2",
173
+ "format" => "optional",
174
+ ),
175
+ "Carrier Grid 3" => array(
176
+ "name" => "Carrier Grid 3",
177
+ "feed_name" => "carrier_grid_3",
178
+ "format" => "optional",
179
+ ),
180
+ "Shipping time carrier grid 3" => array(
181
+ "name" => "Shipping time carrier grid 3",
182
+ "feed_name" => "shipping_time_carrier_grid_3",
183
+ "format" => "optional",
184
+ ),
185
+ "Carrier Grid 4" => array(
186
+ "name" => "Carrier Grid 4",
187
+ "feed_name" => "carrier_grid_4",
188
+ "format" => "optional",
189
+ ),
190
+ "Shipping time carrier grid 4" => array(
191
+ "name" => "Shipping time carrier grid 4",
192
+ "feed_name" => "shipping_time_carrier_grid_4",
193
+ "format" => "optional",
194
+ ),
195
+ "Free Return" => array(
196
+ "name" => "Free Return",
197
+ "feed_name" => "free_return",
198
+ "format" => "optional",
199
+ ),
200
+ "Min quantity" => array(
201
+ "name" => "Min quantity",
202
+ "feed_name" => "min_quantity",
203
+ "format" => "optional",
204
+ ),
205
+ "Increment" => array(
206
+ "name" => "Increment",
207
+ "feed_name" => "increment",
208
+ "format" => "optional",
209
+ ),
210
+ "Sales" => array(
211
+ "name" => "Sales",
212
+ "feed_name" => "sales",
213
+ "format" => "optional",
214
+ ),
215
+ "Eco participation" => array(
216
+ "name" => "Eco participation",
217
+ "feed_name" => "eco_participation",
218
+ "format" => "optional",
219
+ ),
220
+ "Price per m2 vat inc" => array(
221
+ "name" => "Price per m2 vat inc",
222
+ "feed_name" => "Price_per_m2_vat_inc",
223
+ "format" => "optional",
224
+ ),
225
+ "Shipping price supplement vat inc" => array(
226
+ "name" => "Shipping price supplement vat inc",
227
+ "feed_name" => "shipping_price_supplement_vat_inc",
228
+ "format" => "optional",
229
+ ),
230
+ "Feature1" => array(
231
+ "name" => "Feature1",
232
+ "feed_name" => "feature1",
233
+ "format" => "optional",
234
+ ),
235
+ "Color" => array(
236
+ "name" => "Color",
237
+ "feed_name" => "Color",
238
+ "format" => "optional",
239
+ ),
240
+ "Special price type" => array(
241
+ "name" => "Special price type",
242
+ "feed_name" => "special_price_type",
243
+ "format" => "optional",
244
+ ),
245
+ "Sample SKU" => array(
246
+ "name" => "Sample SKU",
247
+ "feed_name" => "Sample_SKU",
248
+ "format" => "optional",
249
+ ),
250
+ "Style" => array(
251
+ "name" => "Style",
252
+ "feed_name" => "Style",
253
+ "format" => "optional",
254
+ ),
255
+ "Unit count" => array(
256
+ "name" => "Unit count",
257
+ "feed_name" => "unit_count",
258
+ "format" => "optional",
259
+ ),
260
+ "Unit count type" => array(
261
+ "name" => "Unit count type",
262
+ "feed_name" => "unit_count_type",
263
+ "format" => "optional",
264
+ ),
265
+ ),
266
+ );
267
+ return $manomano;
268
+ }
269
+ }
270
+ ?>
classes/class-activate.php CHANGED
@@ -16,6 +16,13 @@ class WooSEA_Activation {
16
  "taxonomy" => "google_shopping",
17
  "utm_source" => "Google Shopping",
18
  "type" => "Advertising" ),
 
 
 
 
 
 
 
19
  "Google Remarketing - DRM" => array (
20
  "channel_hash" => md5("Google Remarketing"),
21
  "name" => "Google Remarketing - DRM",
@@ -125,7 +132,7 @@ class WooSEA_Activation {
125
  "Beslist.be" => array (
126
  "channel_hash" => md5("Beslist.be"),
127
  "name" => "Beslist.be",
128
- "fields" => "customfeed",
129
  "taxonomy" => "none",
130
  "utm_source" => "Beslist.be",
131
  "type" => "Comparison shopping engine" ),
@@ -914,6 +921,13 @@ class WooSEA_Activation {
914
  "taxonomy" => "none",
915
  "utm_source" => "Spartoo.it",
916
  "type" => "Marketplace" ),
 
 
 
 
 
 
 
917
  ),
918
  "Ivory Coast" => array (),
919
  "Jamaica" => array (),
@@ -1035,10 +1049,17 @@ class WooSEA_Activation {
1035
  "Beslist.nl" => array (
1036
  "channel_hash" => md5("Beslist.nl"),
1037
  "name" => "Beslist.nl",
1038
- "fields" => "customfeed",
1039
  "taxonomy" => "none",
1040
  "utm_source" => "Beslist.nl",
1041
  "type" => "Comparison shopping engine" ),
 
 
 
 
 
 
 
1042
  "Marktplaats.nl" => array (
1043
  "channel_hash" => md5("Marktplaats.nl"),
1044
  "name" => "Marktplaats.nl",
@@ -1433,7 +1454,14 @@ class WooSEA_Activation {
1433
  "taxonomy" => "none",
1434
  "utm_source" => "Frugoo.com",
1435
  "type" => "Marketplace" ),
1436
- "Choozen" => array (
 
 
 
 
 
 
 
1437
  "channel_hash" => md5("Choozen.co.uk"),
1438
  "name" => "Choozen.co.uk",
1439
  "fields" => "customfeed",
@@ -1669,6 +1697,13 @@ class WooSEA_Activation {
1669
  wp_schedule_event ( time(), 'hourly', 'woosea_cron_hook');
1670
  }
1671
 
 
 
 
 
 
 
 
1672
  /**
1673
  * We check only once if this is a paid version of the plugin
1674
  * De-register the jQuery code after 30 secvonds
@@ -1685,5 +1720,28 @@ class WooSEA_Activation {
1685
  $notifications_obj = new WooSEA_Get_Admin_Notifications;
1686
  $notifications_box = $notifications_obj->get_admin_notifications ( "1", "false" );
1687
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1688
  }
1689
  }
16
  "taxonomy" => "google_shopping",
17
  "utm_source" => "Google Shopping",
18
  "type" => "Advertising" ),
19
+ "Google Merchant Promotions Feed" => array (
20
+ "channel_hash" => md5("Google Merchant Promotions Feed"),
21
+ "name" => "Google Merchant Promotions Feed",
22
+ "fields" => "google_shopping_promotions",
23
+ "taxonomy" => "none",
24
+ "utm_source" => "Google Shopping",
25
+ "type" => "Advertising" ),
26
  "Google Remarketing - DRM" => array (
27
  "channel_hash" => md5("Google Remarketing"),
28
  "name" => "Google Remarketing - DRM",
132
  "Beslist.be" => array (
133
  "channel_hash" => md5("Beslist.be"),
134
  "name" => "Beslist.be",
135
+ "fields" => "beslist",
136
  "taxonomy" => "none",
137
  "utm_source" => "Beslist.be",
138
  "type" => "Comparison shopping engine" ),
921
  "taxonomy" => "none",
922
  "utm_source" => "Spartoo.it",
923
  "type" => "Marketplace" ),
924
+ "Kijiji" => array (
925
+ "channel_hash" => md5("Kijiji.it"),
926
+ "name" => "Kijiji.it",
927
+ "fields" => "kijiji",
928
+ "taxonomy" => "none",
929
+ "utm_source" => "Kijiji.it",
930
+ "type" => "Marketplace" ),
931
  ),
932
  "Ivory Coast" => array (),
933
  "Jamaica" => array (),
1049
  "Beslist.nl" => array (
1050
  "channel_hash" => md5("Beslist.nl"),
1051
  "name" => "Beslist.nl",
1052
+ "fields" => "beslist",
1053
  "taxonomy" => "none",
1054
  "utm_source" => "Beslist.nl",
1055
  "type" => "Comparison shopping engine" ),
1056
+ "Miinto" => array (
1057
+ "channel_hash" => md5("Miinto.nl"),
1058
+ "name" => "Miinto.nl",
1059
+ "fields" => "customfeed",
1060
+ "taxonomy" => "none",
1061
+ "utm_source" => "Miinto.nl",
1062
+ "type" => "Comparison shopping engine" ),
1063
  "Marktplaats.nl" => array (
1064
  "channel_hash" => md5("Marktplaats.nl"),
1065
  "name" => "Marktplaats.nl",
1454
  "taxonomy" => "none",
1455
  "utm_source" => "Frugoo.com",
1456
  "type" => "Marketplace" ),
1457
+ "ManoMano" => array (
1458
+ "channel_hash" => md5("ManoMano.co.uk"),
1459
+ "name" => "ManoMano.co.uk",
1460
+ "fields" => "manomano",
1461
+ "taxonomy" => "none",
1462
+ "utm_source" => "ManoMano.co.uk",
1463
+ "type" => "Marketplace" ),
1464
+ "Choozen" => array (
1465
  "channel_hash" => md5("Choozen.co.uk"),
1466
  "name" => "Choozen.co.uk",
1467
  "fields" => "customfeed",
1697
  wp_schedule_event ( time(), 'hourly', 'woosea_cron_hook');
1698
  }
1699
 
1700
+ /**
1701
+ * Function for checking if license is valid
1702
+ */
1703
+ if (!wp_next_scheduled( 'woosea_check_license' ) ) {
1704
+ wp_schedule_event ( time(), 'twicedaily', 'woosea_check_license');
1705
+ }
1706
+
1707
  /**
1708
  * We check only once if this is a paid version of the plugin
1709
  * De-register the jQuery code after 30 secvonds
1720
  $notifications_obj = new WooSEA_Get_Admin_Notifications;
1721
  $notifications_box = $notifications_obj->get_admin_notifications ( "1", "false" );
1722
  }
1723
+
1724
+ /**
1725
+ * Disable structured data JSON=LD changes by default
1726
+ * User needs to enable this setting in the plugin section
1727
+ */
1728
+ update_option( 'structured_data_fix', 'no', 'yes');
1729
+
1730
+ /**
1731
+ * Register date of first activation of plugin
1732
+ * We need this date in order to only show the
1733
+ * Review notification request once
1734
+ */
1735
+ if(!get_option( 'woosea_first_activation')){
1736
+ update_option ( 'woosea_first_activation', time(), 'yes');
1737
+ }
1738
+
1739
+ if(!get_option( 'woosea_count_activation')){
1740
+ update_option ( 'woosea_count_activation', 1, 'yes');
1741
+ } else {
1742
+ $count_activation = get_option ( 'woosea_count_activation' );
1743
+ $new_activation = $count_activation+1;
1744
+ update_option ( 'woosea_count_activation', $new_activation, 'yes');
1745
+ }
1746
  }
1747
  }
classes/class-admin-notifications.php CHANGED
@@ -9,7 +9,7 @@ class WooSEA_Get_Admin_Notifications {
9
  $this->notification_details = array();
10
  }
11
 
12
- public function woosea_debug_informations ($versions, $product_numbers, $cron_objects) {
13
  $upload_dir = wp_upload_dir();
14
  $filename = "debug";
15
 
@@ -40,21 +40,24 @@ class WooSEA_Get_Admin_Notifications {
40
  fwrite($fp, print_r($versions, TRUE));
41
  fwrite($fp, print_r($product_numbers, TRUE));
42
  fwrite($fp, print_r($cron_objects, TRUE));
 
43
  fclose($fp);
44
 
45
  return $this->notification_details = $external_file;
46
  }
47
 
48
  public function get_admin_notifications ( $step, $error ) {
 
 
49
 
50
  switch($step){
51
  case 0:
52
  $message = "Please select the country and channel for which you would like to create a new product feed. The channel drop-down will populate with relevant country channels once you selected a country. Filling in a project name is mandatory.";
53
- $message_type = "notice notice-info is-dismissible";
54
  break;
55
  case 1:
56
  $message = "Map your products or categories to the categories of your selected channel. For some channels adding their categorisation in the product feed is mandatory. Even when category mappings are not mandatory it is likely your products will get better visibility and higher conversions when mappings have been added.";
57
- $message_type = "notice notice-info is-dismissible";
58
  break;
59
  case 2:
60
  $message = "Please drag and drop the attributes you want to be in your product feed from left to right.";
@@ -65,12 +68,12 @@ class WooSEA_Get_Admin_Notifications {
65
  $message_type = "notice notice-info is-dismissible";
66
  break;
67
  case 4:
68
- $message = "Create filter and rules so exactly the right products end up in your product feed. These filters and rules are only eligable for the current product feed you are configuring and will not be used for other feeds.<br/><br/><strong>Filters:</strong> Exclude or include products that meet certain conditions.<br/><strong>Rules:</strong> Change attribute values based on other attribute values or conditions.<br/><br/>Order of execution: the filters and rules will be executed in the order of creation.";
69
- $message_type = "notice notice-info is-dismissible";
70
  break;
71
  case 5:
72
  $message = "<strong>Conversion tracking:</strong><br/>Enable conversion tracking if you want the plugin to keep track of sales and conversions coming from your product feed. When enabled an AdTribesID parameter will be added to your landingpage URL's.<br/><br/><strong>Google Analytics UTM codes:</strong><br/>Adding Google Analytics UTM codes is not mandatory, it will however enable you to get detailed insights into how your products are performing in Google Analytics reporting and allow you to tweak and tune your campaign making it more profitable. We strongly advise you to add the Google Analytics tracking. When enabled the plugin will append the Google Analytics UTM parameters to your landingpage URL's.";
73
- $message_type = "notice notice-info is-dismissible";
74
  break;
75
  case 6:
76
  $message = "Your product feed is now being created, please be patient. Your feed details will be displayed when generation of the product feed has been finished.";
@@ -78,11 +81,11 @@ class WooSEA_Get_Admin_Notifications {
78
  break;
79
  case 7:
80
  $message = "For the selected channel the attributes shown below are mandatory, please map them to your product attributes. We've already pre-filled a lot of mappings so all you have to do is check those and map the ones that are left blank or add new ones by hitting the 'Add field mapping' button.";
81
- $message_type = "notice notice-info is-dismissible";
82
  break;
83
  case 8:
84
  $message = "Manage your projects, such as the mappings and filter rules, below. Hit the refresh icon for the project to run with its new settings or just to refresh the product feed. When a project is being processed it is not possible to make changes to its configuration.";
85
- $message_type = "notice notice-info is-dismissible";
86
  break;
87
  case 9:
88
  $message = "You cannot create product feeds yet, please install WooCommerce first.";
@@ -105,8 +108,8 @@ class WooSEA_Get_Admin_Notifications {
105
  $message_type = "notice notice-error is-dismissible";
106
  break;
107
  case 14:
108
- $message = "Grant access to our customer service to help you with creating product feed configurations. Enabling this option will create a new WordPress user. Credentials will automatically be send to AdTribes.io support team. By disabling this option the Wordpress user will be deleted.";
109
- $message_type = "notice notice-info is-dismissible";
110
  break;
111
  }
112
 
9
  $this->notification_details = array();
10
  }
11
 
12
+ public function woosea_debug_informations ($versions, $product_numbers, $order_rows, $cron_objects) {
13
  $upload_dir = wp_upload_dir();
14
  $filename = "debug";
15
 
40
  fwrite($fp, print_r($versions, TRUE));
41
  fwrite($fp, print_r($product_numbers, TRUE));
42
  fwrite($fp, print_r($cron_objects, TRUE));
43
+ fwrite($fp, print_r($order_rows, TRUE));
44
  fclose($fp);
45
 
46
  return $this->notification_details = $external_file;
47
  }
48
 
49
  public function get_admin_notifications ( $step, $error ) {
50
+
51
+ $domain = $_SERVER['HTTP_HOST'];
52
 
53
  switch($step){
54
  case 0:
55
  $message = "Please select the country and channel for which you would like to create a new product feed. The channel drop-down will populate with relevant country channels once you selected a country. Filling in a project name is mandatory.";
56
+ $message_type = "notice notice-info";
57
  break;
58
  case 1:
59
  $message = "Map your products or categories to the categories of your selected channel. For some channels adding their categorisation in the product feed is mandatory. Even when category mappings are not mandatory it is likely your products will get better visibility and higher conversions when mappings have been added.";
60
+ $message_type = "notice notice-info";
61
  break;
62
  case 2:
63
  $message = "Please drag and drop the attributes you want to be in your product feed from left to right.";
68
  $message_type = "notice notice-info is-dismissible";
69
  break;
70
  case 4:
71
+ $message = "Create filter and rules so exactly the right products end up in your product feed. These filters and rules are only eligable for the current product feed you are configuring and will not be used for other feeds.<br/><br/><strong>Filters:</strong> Exclude or include products that meet certain conditions. [<strong><i><a href=\"https://adtribes.io/how-to-create-filters-for-your-product-feed/\" target=\"_blank\">Detailed information and filter examples</a></i></strong>]<br/><strong>Rules:</strong> Change attribute values based on other attribute values or conditions.<br/><br/>Order of execution: the filters and rules will be executed in the order of creation.";
72
+ $message_type = "notice notice-info";
73
  break;
74
  case 5:
75
  $message = "<strong>Conversion tracking:</strong><br/>Enable conversion tracking if you want the plugin to keep track of sales and conversions coming from your product feed. When enabled an AdTribesID parameter will be added to your landingpage URL's.<br/><br/><strong>Google Analytics UTM codes:</strong><br/>Adding Google Analytics UTM codes is not mandatory, it will however enable you to get detailed insights into how your products are performing in Google Analytics reporting and allow you to tweak and tune your campaign making it more profitable. We strongly advise you to add the Google Analytics tracking. When enabled the plugin will append the Google Analytics UTM parameters to your landingpage URL's.";
76
+ $message_type = "notice notice-info";
77
  break;
78
  case 6:
79
  $message = "Your product feed is now being created, please be patient. Your feed details will be displayed when generation of the product feed has been finished.";
81
  break;
82
  case 7:
83
  $message = "For the selected channel the attributes shown below are mandatory, please map them to your product attributes. We've already pre-filled a lot of mappings so all you have to do is check those and map the ones that are left blank or add new ones by hitting the 'Add field mapping' button.";
84
+ $message_type = "notice notice-info";
85
  break;
86
  case 8:
87
  $message = "Manage your projects, such as the mappings and filter rules, below. Hit the refresh icon for the project to run with its new settings or just to refresh the product feed. When a project is being processed it is not possible to make changes to its configuration.";
88
+ $message_type = "notice notice-info";
89
  break;
90
  case 9:
91
  $message = "You cannot create product feeds yet, please install WooCommerce first.";
108
  $message_type = "notice notice-error is-dismissible";
109
  break;
110
  case 14:
111
+ $message = "Grant access to our customer service to help you with creating product feed configurations. Enabling this option will create a new WordPress user. Credentials will automatically be send to AdTribes.io support team. By disabling this option the Wordpress user will be deleted.<br/><br/><strong>Please note:<br/></strong>The addition of extra attributes to your store and the JSON-LD features are part of our <a href=\"https://adtribes.io/pro-vs-elite/?utm_source=$domain&utm_medium=plugin&utm_campaign=upgrade-elite\" target=\"_blank\">Elite membership</a>.";
112
+ $message_type = "notice notice-info";
113
  break;
114
  }
115
 
classes/class-attributes.php CHANGED
@@ -48,8 +48,8 @@ private function get_dynamic_attributes(){
48
  global $wpdb;
49
  $list = array();
50
 
51
- $no_taxonomies = array("yst_prominent_words","category","post_tag","nav_menu","link_category","post_format","product_type","product_visibility","product_cat","product_shipping_class","product_tag");
52
- $taxonomies = get_taxonomies();
53
  $diff_taxonomies = array_diff($taxonomies, $no_taxonomies);
54
 
55
  # get custom taxonomy values for a product
@@ -81,10 +81,11 @@ private function get_custom_attributes() {
81
  $sql = "SELECT meta_key as name, meta_value as type FROM " . $wpdb->prefix . "postmeta" . " group by meta_key";
82
  $data = $wpdb->get_results($sql);
83
 
 
84
  if (count($data)) {
85
  foreach ($data as $key => $value) {
86
- if (substr($value->name, 0, 1) !== "_") {
87
- $value_display = str_replace("_", " ",$value->name);
88
  $list["custom_attributes_" . $value->name] = ucfirst($value_display);
89
  }
90
  }
@@ -178,8 +179,12 @@ public function get_mapping_attributes_dropdown() {
178
  "net_price" => "Price excl. VAT",
179
  "net_regular_price" => "Regular price excl. VAT",
180
  "net_sale_price" => "Sale price excl. VAT",
181
- "sale_price_start_date" => "Sale start date",
 
 
 
182
  "sale_price_end_date" => "Sale end date",
 
183
  "link" => "Link",
184
  "currency" => "Currency",
185
  "categories" => "Category",
@@ -189,6 +194,7 @@ public function get_mapping_attributes_dropdown() {
189
  "availability" => "Availability",
190
  "quantity" => "Quantity [Stock]",
191
  "product_type" => "Product Type",
 
192
  "item_group_id" => "Item group ID",
193
  "weight" => "Weight",
194
  "width" => "Width",
@@ -254,73 +260,24 @@ public function get_mapping_attributes_dropdown() {
254
  $dropdown .="</optgroup>";
255
  }
256
 
257
- /**
258
- * Create dropdown with product attributes
259
- */
260
-
261
- // Get Attributes for Single products
262
- $post_type = array('product');
263
-
264
- // Construct WP query
265
- $wp_query = array(
266
- 'post_type' => $post_type,
267
- 'post_status' => 'publish',
268
- 'posts_per_page' => -1,
269
- 'fields' => 'ids',
270
- 'no_found_rows' => true,
271
- 'meta_query' => array(
272
- array(
273
- 'key' => '_product_attributes',
274
- 'compare' => 'LIKE',
275
- ),
276
- ),
277
- );
278
- $prods = new WP_Query($wp_query);
279
-
280
- $no_taxonomies = array("category","post_tag","nav_menu","link_category","post_format","product_type","product_visibility","product_cat","product_shipping_class","product_tag");
281
- $taxonomies = get_taxonomies();
282
- $diff_taxonomies = array_diff($taxonomies, $no_taxonomies);
283
- $prod_attr = array();
284
-
285
  $dropdown .= "<optgroup label='Google category taxonomy'><strong>Google category taxonomy</strong>";
286
  $dropdown .= "<option value='google_category'>Google category</option>";
287
-
288
- while ($prods->have_posts()) : $prods->the_post();
289
- global $product;
290
- $prod_attributes = $product->get_attributes();
291
-
292
- foreach($prod_attributes as $prod_attribute){
293
- $prod_attribute_name = $prod_attribute->get_name();
294
- if(!in_array($prod_attribute_name, $prod_attr, true)){
295
- $prod_attribute_name_key = "pa_".$prod_attribute_name;
296
- $prod_attribute_name_key = str_replace(" ", "_", $prod_attribute_name_key);
297
-
298
- $attr = array (
299
- $prod_attribute_name_key => $prod_attribute_name ." (Product attribute)"
300
- );
301
- $prod_attr = array_merge($prod_attr, $attr);
302
- }
303
- }
304
-
305
- endwhile;
306
-
307
- foreach ($prod_attr as $prod_key => $prod_value){
308
- $dropdown .= "<option value='$prod_key'>" . ucfirst($prod_value) . "</option>";
309
- }
310
-
311
  $dropdown .="</optgroup>";
312
 
313
  /**
314
  * Create dropdown with custom attributes
315
  */
316
  $custom_attributes = $this->get_custom_attributes();
 
317
  if($custom_attributes){
318
- $dropdown .= "<optgroup label='Custom attributes'><strong>Custom attributes</strong>";
319
 
320
  foreach ($custom_attributes as $key => $value) {
321
- if (strpos($value, 0, 1) !== "_") {
322
- $dropdown .= "<option value='$key'>" . ucfirst($value) . "</option>";
323
- }
 
 
324
  }
325
 
326
  $dropdown .="</optgroup>";
@@ -342,9 +299,11 @@ public function get_mapping_attributes_dropdown() {
342
  "image" => "Main image",
343
  "feature_image" => "Feature image",
344
  "product_type" => "Product Type",
345
- "currency" => "Currency",
 
346
  "categories" => "Category",
347
- "google_category" => "Google category",
 
348
  "category_link" => "Category link",
349
  "category_path" => "Category path",
350
  "condition" => "Condition",
@@ -356,8 +315,12 @@ public function get_mapping_attributes_dropdown() {
356
  "net_price" => "Price excl. VAT",
357
  "net_regular_price" => "Regular price excl. VAT",
358
  "net_sale_price" => "Sale price excl. VAT",
 
 
 
359
  "sale_price_start_date" => "Sale start date",
360
  "sale_price_end_date" => "Sale end date",
 
361
  "item_group_id" => "Item group ID",
362
  "weight" => "Weight",
363
  "width" => "Width",
@@ -367,6 +330,7 @@ public function get_mapping_attributes_dropdown() {
367
  "visibility" => "Visibility",
368
  "rating_total" => "Total rating",
369
  "rating_average" => "Average rating",
 
370
  );
371
 
372
  $images = array(
@@ -388,7 +352,6 @@ public function get_mapping_attributes_dropdown() {
388
 
389
  if(is_array($this->get_dynamic_attributes())){
390
  $dynamic_attributes = $this->get_dynamic_attributes();
391
-
392
  array_walk($dynamic_attributes, function(&$value, $key) { $value .= ' (Dynamic attribute)';});
393
  $attributes = array_merge($attributes, $dynamic_attributes);
394
  }
@@ -399,58 +362,16 @@ public function get_mapping_attributes_dropdown() {
399
  $attributes = array_merge($attributes, $custom_attributes);
400
  }
401
 
402
- // Get Attributes for Single products
403
- $post_type = array('product');
404
-
405
- // Construct WP query
406
- $wp_query = array(
407
- 'post_type' => $post_type,
408
- 'post_status' => 'publish',
409
- 'posts_per_page' => -1,
410
- 'fields' => 'ids',
411
- 'no_found_rows' => true,
412
- 'meta_query' => array(
413
- array(
414
- 'key' => '_product_attributes',
415
- 'compare' => 'LIKE',
416
- ),
417
- ),
418
- );
419
- $prods = new WP_Query($wp_query);
420
- $prod_attr = array();
421
-
422
- $t = 1;
423
-
424
- while ($prods->have_posts()) : $prods->the_post();
425
- global $product;
426
-
427
- $prod_attributes = $product->get_attributes();
428
-
429
- if($prod_attributes){
430
- foreach($prod_attributes as $prod_attribute){
431
- $prod_attribute_name = $prod_attribute->get_name();
432
- $prod_attribute_name_key = "pa_".$prod_attribute_name;
433
- $prod_attribute_name_key = str_replace(" ", "_", $prod_attribute_name_key);
434
-
435
- $attr = array (
436
- $prod_attribute_name_key => $prod_attribute_name ." (Product attribute)"
437
- );
438
- $prod_attr = array_merge($prod_attr, $attr);
439
- }
440
- }
441
- endwhile;
442
 
443
  $static = array(
444
  "static_value" => "Static value",
445
  "calculated" => "Plugin calculation",
446
  );
447
 
448
- $attributes = array_merge($attributes, $prod_attr, $static);
449
-
450
  return $attributes;
451
  }
452
 
453
-
454
  public static function get_standard_attributes($project) {
455
  $sitename = get_option('blogname');
456
 
48
  global $wpdb;
49
  $list = array();
50
 
51
+ $no_taxonomies = array("element_category","template_category","portfolio_category","portfolio_skills","portfolio_tags","faq_category","slide-page","yst_prominent_words","category","post_tag","nav_menu","link_category","post_format","product_type","product_visibility","product_cat","product_shipping_class","product_tag");
52
+ $taxonomies = get_taxonomies();
53
  $diff_taxonomies = array_diff($taxonomies, $no_taxonomies);
54
 
55
  # get custom taxonomy values for a product
81
  $sql = "SELECT meta_key as name, meta_value as type FROM " . $wpdb->prefix . "postmeta" . " group by meta_key";
82
  $data = $wpdb->get_results($sql);
83
 
84
+
85
  if (count($data)) {
86
  foreach ($data as $key => $value) {
87
+ if (!preg_match("/pyre|sbg|fusion/i",$value->name)){
88
+ $value_display = str_replace("_", " ",$value->name);
89
  $list["custom_attributes_" . $value->name] = ucfirst($value_display);
90
  }
91
  }
179
  "net_price" => "Price excl. VAT",
180
  "net_regular_price" => "Regular price excl. VAT",
181
  "net_sale_price" => "Sale price excl. VAT",
182
+ "price_forced" => "Price incl. VAT front end",
183
+ "regular_price_forced" => "Regular price incl. VAT front end",
184
+ "sale_price_forced" => "Sale price incl. VAT front end",
185
+ "sale_price_start_date" => "Sale start date",
186
  "sale_price_end_date" => "Sale end date",
187
+ "sale_price_effective_date" => "Sale price effective date",
188
  "link" => "Link",
189
  "currency" => "Currency",
190
  "categories" => "Category",
194
  "availability" => "Availability",
195
  "quantity" => "Quantity [Stock]",
196
  "product_type" => "Product Type",
197
+ "publication_date" => "Publication date",
198
  "item_group_id" => "Item group ID",
199
  "weight" => "Weight",
200
  "width" => "Width",
260
  $dropdown .="</optgroup>";
261
  }
262
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
  $dropdown .= "<optgroup label='Google category taxonomy'><strong>Google category taxonomy</strong>";
264
  $dropdown .= "<option value='google_category'>Google category</option>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
  $dropdown .="</optgroup>";
266
 
267
  /**
268
  * Create dropdown with custom attributes
269
  */
270
  $custom_attributes = $this->get_custom_attributes();
271
+
272
  if($custom_attributes){
273
+ $dropdown .= "<optgroup label='Custom field attributes'><strong>Custom field attributes</strong>";
274
 
275
  foreach ($custom_attributes as $key => $value) {
276
+ if (!preg_match("/pyre|sbg|fusion/i",$value)){
277
+ if (strpos($value, 0, 1) !== "_") {
278
+ $dropdown .= "<option value='$key'>" . ucfirst($value) . "</option>";
279
+ }
280
+ }
281
  }
282
 
283
  $dropdown .="</optgroup>";
299
  "image" => "Main image",
300
  "feature_image" => "Feature image",
301
  "product_type" => "Product Type",
302
+ "publication_date" => "Publication date",
303
+ "currency" => "Currency",
304
  "categories" => "Category",
305
+ "raw_categories" => "Category (not used for mapping)",
306
+ "google_category" => "Google category (for rules and filters only)",
307
  "category_link" => "Category link",
308
  "category_path" => "Category path",
309
  "condition" => "Condition",
315
  "net_price" => "Price excl. VAT",
316
  "net_regular_price" => "Regular price excl. VAT",
317
  "net_sale_price" => "Sale price excl. VAT",
318
+ "price_forced" => "Price incl. VAT front end",
319
+ "regular_price_forced" => "Regular price incl. VAT front end",
320
+ "sale_price_forced" => "Sale price incl. VAT front end",
321
  "sale_price_start_date" => "Sale start date",
322
  "sale_price_end_date" => "Sale end date",
323
+ "sale_price_effective_date" => "Sale price effective date",
324
  "item_group_id" => "Item group ID",
325
  "weight" => "Weight",
326
  "width" => "Width",
330
  "visibility" => "Visibility",
331
  "rating_total" => "Total rating",
332
  "rating_average" => "Average rating",
333
+ "amount_sales" => "Amount of sales",
334
  );
335
 
336
  $images = array(
352
 
353
  if(is_array($this->get_dynamic_attributes())){
354
  $dynamic_attributes = $this->get_dynamic_attributes();
 
355
  array_walk($dynamic_attributes, function(&$value, $key) { $value .= ' (Dynamic attribute)';});
356
  $attributes = array_merge($attributes, $dynamic_attributes);
357
  }
362
  $attributes = array_merge($attributes, $custom_attributes);
363
  }
364
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
365
 
366
  $static = array(
367
  "static_value" => "Static value",
368
  "calculated" => "Plugin calculation",
369
  );
370
 
371
+ $attributes = array_merge($attributes, $static);
 
372
  return $attributes;
373
  }
374
 
 
375
  public static function get_standard_attributes($project) {
376
  $sitename = get_option('blogname');
377
 
classes/class-deactivate-cleanup.php CHANGED
@@ -7,6 +7,9 @@
7
  class WooSEA_Deactivate_Cleanup {
8
  public static function deactivate_cleanup() {
9
  wp_clear_scheduled_hook('woosea_cron_hook');
 
10
  delete_option( 'channel_statics');
 
 
11
  }
12
  }
7
  class WooSEA_Deactivate_Cleanup {
8
  public static function deactivate_cleanup() {
9
  wp_clear_scheduled_hook('woosea_cron_hook');
10
+ wp_clear_scheduled_hook('woosea_check_license');
11
  delete_option( 'channel_statics');
12
+ delete_option('license_information');
13
+ // delete_option( 'cron_projects' );
14
  }
15
  }
classes/class-get-products.php CHANGED
@@ -33,6 +33,14 @@ class WooSEA_Get_Products {
33
  return $product_cats;
34
  }
35
 
 
 
 
 
 
 
 
 
36
  /**
37
  * Function that will create an append with Google Analytics UTM parameters
38
  * Removes UTM paramaters that are left blank
@@ -81,13 +89,80 @@ class WooSEA_Get_Products {
81
  return $utm_part;
82
  }
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  /**
85
  * Get category path (needed for Prisjakt)
86
  */
87
- public function woosea_get_term_parents( $id, $taxonomy, $link = false, $separator = '/', $nicename = false, $visited = array() ) {
88
- $chain = '';
 
 
 
 
 
 
89
  $parent = get_term( $id, $taxonomy );
90
-
 
 
 
 
 
91
  if ( is_wp_error( $parent ) )
92
  return $parent;
93
 
@@ -99,13 +174,13 @@ class WooSEA_Get_Products {
99
 
100
  if ($parent->parent && ( $parent->parent != $parent->term_id ) && !in_array( $parent->parent, $visited )){
101
  $visited[] = $parent->parent;
102
- $chain .= WooSEA_Get_Products::woosea_get_term_parents( $parent->parent, $taxonomy, $link, $separator, $nicename, $visited );
103
  }
104
 
105
  if ($link){
106
- $chain .= '<a href="' . get_term_link( $parent, $taxonomy ) . '" title="' . esc_attr( sprintf( __( "View all posts in %s" ), $parent->name ) ) . '">'.$parent->name.'</a>' . $separator;
107
  } else {
108
- $chain .= $name.$separator;
109
  }
110
  return $chain;
111
  } // End woo_get_term_parents()
@@ -134,6 +209,7 @@ class WooSEA_Get_Products {
134
  $base_country = $base_location['country'];
135
 
136
  foreach ( $shipping_zones as $zone){
 
137
  $zone_details = array();
138
  $zone_code = $zone['zone_locations'][0]->code;
139
  $zone_details['country'] = $zone_code;
@@ -142,7 +218,10 @@ class WooSEA_Get_Products {
142
  if(isset($zone['zone_locations'][1]->code)){
143
  $zone_region = $zone['zone_locations'][1]->code;
144
  $zn_short = explode (":", $zone_region);
145
- $zone_details['region'] = $zn_short[1];
 
 
 
146
  }
147
 
148
  // When no shipping zone has been configured in project take the shops country zone id as default
@@ -155,9 +234,8 @@ class WooSEA_Get_Products {
155
 
156
  foreach ( $arr_shipping_methods as $shipping ) {
157
 
158
-
159
  // FLAT RATE SHIPPING COSTS
160
- if($shipping['instance_settings']['title'] == "Flat rate"){
161
  if(isset($shipping['instance_settings']['cost'])){
162
  $zone_details['service'] = $shipping['instance_settings']['title'];
163
  $shipping_cost = $shipping['instance_settings']['cost'];
@@ -168,7 +246,7 @@ class WooSEA_Get_Products {
168
  $zone_details['service'] = $shipping['instance_settings']['title'];
169
  $shipping_cost = ($shipping['instance_settings'][$class_cost_id]+$shipping_cost);
170
  }
171
- }
172
 
173
  // FREE SHIPPING COSTS
174
  if($shipping['instance_settings']['title'] == "Free shipping"){
@@ -180,7 +258,7 @@ class WooSEA_Get_Products {
180
  }
181
 
182
  foreach ($tax_rates as $k => $v){
183
- if($v['shipping'] == "yes"){
184
  $rate = (($v['rate']+100)/100);
185
  $shipping_cost = $shipping_cost*$rate;
186
  $shipping_cost = round($shipping_cost, 2);
@@ -266,14 +344,12 @@ class WooSEA_Get_Products {
266
 
267
  // Some channels need their own feed config and XML namespace declarations (such as Google shopping)
268
  if ($feed_config['taxonomy'] == 'google_shopping'){
269
- $namespace = array(
270
- 'g' => 'http://base.google.com/ns/1.0'
271
- );
272
  if ( ($header == "true") AND ($feed_config['nr_products_processed'] == 0) ) {
273
- $xml = new SimpleXMLElement('<rss xmlns:g="http://base.google.com/ns/1.0"></rss>');
274
  $xml->addAttribute('version', '2.0');
275
  $xml->addChild('channel');
276
- $xml->channel->addChild('title', $feed_config['projectname']);
277
  $xml->channel->addChild('link', site_url());
278
  $xml->channel->addChild('description', 'WooCommerce Product Feed PRO - This product feed is created with the free Advanced WooCommerce Product Feed PRO plugin from AdTribes.io. For all your support questions check out our FAQ on https://www.adtribes.io or e-mail to: support@adtribes.io ');
279
  $xml->asXML($file);
@@ -281,35 +357,42 @@ class WooSEA_Get_Products {
281
  $xml = simplexml_load_file($file, 'SimpleXMLElement', LIBXML_NOCDATA);
282
  $aantal = count($products);
283
 
284
- if ($aantal > 0){
285
- foreach ($products as $key => $value){
286
- if (is_array ( $value ) ) {
287
- $product = $xml->channel->addChild('item');
288
- foreach ($value as $k => $v){
289
- if ($k == "g:shipping"){
290
- $ship = explode("||", $v);
291
- foreach ($ship as $kk => $vv){
292
- $country_ship = explode(":", $vv);
 
 
 
 
 
 
293
 
294
- $shipping = $product->addChild($k, '', $namespace['g']);
295
- $shipping_country = $shipping->addChild('g:country', $country_ship[0], $namespace['g']);
296
- $shipping_region = $shipping->addChild('g:region', $country_ship[2], $namespace['g']);
297
- $shipping_service = $shipping->addChild('g:service', $country_ship[1], $namespace['g']);
298
- $shipping_price = $shipping->addChild('g:price', $country_ship[3], $namespace['g']);
 
 
 
 
 
 
 
 
299
  }
300
- // Fix issue with additional images for Google Shopping
301
- } elseif (preg_match("/g:additional_image_link/i",$k)){
302
- $link = $product->addChild('g:additional_image_link', $v, $namespace['g']);
303
- //$product->$k = $v;
304
- } else {
305
- $product->$k = $v;
306
  }
307
- }
308
- }
309
  }
310
- $xml->asXML($file);
311
- unset($product);
312
  }
 
313
  unset($products);
314
  }
315
  unset($xml);
@@ -353,7 +436,7 @@ class WooSEA_Get_Products {
353
  $xml->asXML($file);
354
  } elseif ($feed_config['name'] == "Heureka.cz") {
355
  $xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><SHOP></SHOP>');
356
- $xml->addAttribute('xmlns', 'https://www.zbozi.cz/ns/offer/1.0/');
357
  $xml->asXML($file);
358
  } else {
359
  $xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><products></products>');
@@ -463,7 +546,7 @@ class WooSEA_Get_Products {
463
  // Do not add these nodes to Yandex product feeds
464
  } else {
465
  if ($feed_config['fields'] != 'standard'){
466
- $k = WooSEA_Get_Products::get_alternative_key ($channel_attributes, $k);
467
  }
468
 
469
  if(!empty($k)){
@@ -506,7 +589,7 @@ class WooSEA_Get_Products {
506
 
507
  // Check if file exists, if it does: delete it first so we can create a new updated one
508
  if ( (file_exists( $file )) AND ($feed_config['nr_products_processed'] == 0) AND ($header == "true") ) {
509
- unlink ( $file );
510
  }
511
 
512
  // Check if there is a channel feed class that we need to use
@@ -533,7 +616,7 @@ class WooSEA_Get_Products {
533
 
534
  foreach ($pieces as $k => $v){
535
  if ($feed_config['fields'] != 'standard'){
536
- $v = WooSEA_Get_Products::get_alternative_key ($channel_attributes, $v);
537
  }
538
 
539
  // For CSV fileformat the keys need to get stripped of the g:
@@ -543,7 +626,14 @@ class WooSEA_Get_Products {
543
 
544
  $pieces[$k] = $v;
545
  }
546
- $blaat = fputcsv($fp, $pieces, $feed_config['delimiter'], '"');
 
 
 
 
 
 
 
547
  }
548
  }
549
  // Close the file
@@ -578,6 +668,14 @@ class WooSEA_Get_Products {
578
  "Plugin" => WOOCOMMERCESEA_PLUGIN_VERSION
579
  );
580
 
 
 
 
 
 
 
 
 
581
  /**
582
  * Do not change these settings, they are here to prevent running into memory issues
583
  */
@@ -588,8 +686,14 @@ class WooSEA_Get_Products {
588
  // Old version, process a maximum of 100 products per batch
589
  $nr_batches = ceil($published_products/200);
590
  } else {
591
- // Fast PHP version, process a 250 products per batch
592
- $nr_batches = ceil($published_products/500);
 
 
 
 
 
 
593
  }
594
  $offset_step_size = ceil($published_products/$nr_batches);
595
 
@@ -628,11 +732,11 @@ class WooSEA_Get_Products {
628
  $attr = trim($attr, "'");
629
  $products[] = array ( $attr );
630
  if($nr_products_processed == 0){
631
- $file = WooSEA_Get_Products::woosea_create_csvtxt_feed ( $products, $project_config, 'true' );
632
  }
633
  } else {
634
  $products[] = array ();
635
- $file = WooSEA_Get_Products::woosea_create_xml_feed ( $products, $project_config, 'true' );
636
  }
637
  $xml_piece = "";
638
 
@@ -643,6 +747,9 @@ class WooSEA_Get_Products {
643
  $post_type = array('product');
644
  }
645
 
 
 
 
646
  // Construct WP query
647
  $wp_query = array(
648
  'posts_per_page' => $offset_step_size,
@@ -662,7 +769,7 @@ class WooSEA_Get_Products {
662
  // Log the query output for debugging purposes
663
  // $log_query = WooSEA_Get_Products::woosea_create_query_log($prods, "query_output");
664
 
665
- $shipping_zones = WooSEA_GET_Products::woosea_get_shipping_zones();
666
 
667
  while ($prods->have_posts()) : $prods->the_post();
668
  global $product;
@@ -684,7 +791,8 @@ class WooSEA_Get_Products {
684
  $product_data['title'] = $product->get_title();
685
  $product_data['sku'] = $product->get_sku();
686
  $product_data['sku_id'] = $product_data['id'];
687
-
 
688
  if (!empty($product_data['sku'])){
689
  $product_data['sku_id'] = $product_data['sku']."_".$product_data['id'];
690
  }
@@ -697,9 +805,12 @@ class WooSEA_Get_Products {
697
 
698
  $product_id = $product_data['id'];
699
  $primary_cat_id=get_post_meta($product_id ,'_yoast_wpseo_primary_product_cat',true);
700
- $category_path = WooSEA_Get_Products::woosea_get_term_parents( $primary_cat_id, 'product_cat', $link = false, $separator = ' / ', $nicename = false, $visited = array() );
701
- $product_data['category_path'] = $category_path;
702
-
 
 
 
703
  if(($primary_cat_id) AND ($primary_cat_id > 0)){
704
  $product_cat = get_term($primary_cat_id, 'product_cat');
705
 
@@ -735,9 +846,11 @@ class WooSEA_Get_Products {
735
 
736
  // Check if there are mother categories
737
  $parent_categories = get_ancestors($product_cat->term_id, 'product_cat');
738
-
739
- $category_path = WooSEA_Get_Products::woosea_get_term_parents( $product_cat->term_id, 'product_cat', $link = false, $separator = ' / ', $nicename = false, $visited = array() );
740
- $product_data['category_path'] = $category_path;
 
 
741
 
742
  foreach ($parent_categories as $category_id){
743
  $parent = get_term_by('id', $category_id, 'product_cat');
@@ -751,14 +864,17 @@ class WooSEA_Get_Products {
751
  } else {
752
  $product_cat = get_term($value, 'product_cat');
753
 
754
- $category_path = WooSEA_Get_Products::woosea_get_term_parents( $product_cat->term_id, 'product_cat', $link = false, $separator = ' / ', $nicename = false, $visited = array() );
755
- $product_data['category_path'] = $category_path;
756
-
 
 
757
  // Check if there are mother categories
758
  $parent_categories = get_ancestors($product_cat->term_id, 'product_cat');
 
759
  foreach ($parent_categories as $category_id){
760
  $parent = get_term_by('id', $category_id, 'product_cat');
761
- $parent_name .= "||".$parent->name;
762
  }
763
 
764
  if(isset($product_cat->name)) {
@@ -772,29 +888,55 @@ class WooSEA_Get_Products {
772
  }
773
 
774
  $product_data['category_link'] = $catlink;
 
775
  $product_data['categories'] = $catname;
776
- $product_data['description'] = str_replace("\r", "", $post->post_content);
777
- $product_data['short_description'] = str_replace("\r", "", $post->post_excerpt);
778
 
779
  // Strip HTML from (short) description
780
  $product_data['description'] = strip_shortcodes(strip_tags($product_data['description']));
781
  $product_data['short_description'] = strip_shortcodes(strip_tags($product_data['short_description']));
782
 
 
 
 
 
783
  /**
784
  * Check of we need to add Google Analytics UTM parameters
785
  */
786
- $utm_part = WooSEA_Get_Products::woosea_append_utm_code ( $project_config, get_the_ID(), $this->parentID);
 
 
 
 
787
 
788
  $product_data['link'] = get_permalink()."$utm_part";
789
- $product_data['condition'] = "New";
 
 
 
 
790
  $product_data['availability'] = $this->get_stock( $this->childID );
 
 
 
 
 
 
 
 
 
 
 
 
 
791
  $product_data['quantity'] = $this->clean_quantity( $this->childID, "_stock" );
792
  $product_data['visibility'] = $this->get_attribute_value( $this->childID,"_visibility" );
793
  $product_data['currency'] = get_woocommerce_currency();
794
  $product_data['sale_price_start_date'] = $this->get_sale_date($this->childID, "_sale_price_dates_from");
795
  $product_data['sale_price_end_date'] = $this->get_sale_date($this->childID, "_sale_price_dates_to");
 
796
  $product_data['image'] = wp_get_attachment_url($product->get_image_id());
797
-
798
  $gallery_ids = $product->get_gallery_image_ids();
799
  foreach ($gallery_ids as $gallery_key => $gallery_value){
800
  $gal_id = $gallery_key+1;
@@ -814,6 +956,15 @@ class WooSEA_Get_Products {
814
  $product_data['regular_price'] = wc_format_localized_price(wc_get_price_including_tax($product, array('price'=> $product->get_regular_price())));
815
  $product_data['sale_price'] = wc_format_localized_price(wc_get_price_including_tax($product, array('price'=> $product->get_sale_price())));
816
 
 
 
 
 
 
 
 
 
 
817
  // Get net prices
818
  $product_data['net_price'] = wc_format_localized_price($product->get_price());
819
  $product_data['net_regular_price'] = wc_format_localized_price($product->get_regular_price());
@@ -823,7 +974,8 @@ class WooSEA_Get_Products {
823
  if($product_data['sale_price'] > 0){
824
  $price = $product_data['sale_price'];
825
  }
826
- $product_data['shipping'] = WooSEA_Get_Products::woosea_get_shipping_cost($class_cost_id, $project_config, $price, $tax_rates, $shipping_zones);
 
827
 
828
  $shipping_str = "";
829
  foreach ($product_data['shipping'] as $key => $value){
@@ -851,7 +1003,7 @@ class WooSEA_Get_Products {
851
  * Do we need to add Dynamic Attributes?
852
  */
853
  $project_config['attributes_original'] = $project_config['attributes'];
854
-
855
  if($project_config['fields'] != 'standard'){
856
  //$project_config['attributes_original'] = array();
857
  foreach($project_config['attributes'] as $stand_key => $stand_val){
@@ -860,9 +1012,60 @@ class WooSEA_Get_Products {
860
  }
861
  }
862
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
863
 
864
  /**
865
- * Add attributes for Single products
866
  */
867
  if ($product->is_type('simple')){
868
  $single_attributes = $product->get_attributes();
@@ -873,124 +1076,204 @@ class WooSEA_Get_Products {
873
  $product_data[$attr_name] = $attr_value;
874
  }
875
  }
876
-
877
  /**
878
- * Versioned products need a seperate approach, get data for these products
 
879
  */
880
- foreach($project_config['attributes_original'] as $key => $value){
881
- if( ($product_data['item_group_id'] > 0) AND (!is_array($value)) AND ($key == "item_group_id") ){
882
- $product_variations = new WC_Product_Variation( $product_data['id'] );
883
- $variations = $product_variations->get_variation_attributes();
884
- $append = "";
885
-
886
- // User does need to also add the attributes to the feed otherwise they cannot be appended to the productname
887
- foreach($variations as $kk => $vv){
888
- $custom_key = $kk;
889
 
890
- if (isset($project_config['product_variations']) AND ($project_config['product_variations'] == "on")){
891
- $taxonomy = str_replace("attribute_","",$kk);
892
- $term = get_term_by('slug', $vv, $taxonomy);
 
 
 
 
 
 
 
893
 
894
- if($term){
895
- $append = ucfirst($term->name);
 
 
 
 
 
896
  }
 
 
 
 
897
 
898
- $product_data['title'] = $product_data['title']." ".$append;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
899
  }
900
- $product_data[$custom_key] = $vv;
 
 
 
 
901
  }
902
- // Get versioned product categories
903
- $categories = wc_get_product_cat_ids( $product_data['item_group_id'] );
904
-
905
- // Check if the Yoast plugin is installed and active
906
- if ( class_exists('WPSEO_Primary_Term') ){
907
- $product_id = $product_data['item_group_id'];
908
- $primary_cat_id=get_post_meta($product_id ,'_yoast_wpseo_primary_product_cat',true);
909
- if($primary_cat_id){
910
- $product_cat = get_term($primary_cat_id, 'product_cat');
911
- $category_path = WooSEA_Get_Products::woosea_get_term_parents( $product_cat->term_id, 'product_cat', $link = false, $separator = ' / ', $nicename = false, $visited = array() );
912
- $product_data['category_path'] = $category_path;
913
-
914
- if(isset($product_cat->name)) {
915
- $catname = $product_cat->name;
916
- $catlink = get_category_link($product_cat->term_id);
917
- }
918
- } else {
919
- foreach ($categories as $key => $value){
920
- if (!$catname){
921
- $product_cat = get_term($value, 'product_cat');
922
- $category_path = WooSEA_Get_Products::woosea_get_term_parents( $product_cat->term_id, 'product_cat', $link = false, $separator = ' / ', $nicename = false, $visited = array() );
923
- $product_data['category_path'] = $category_path;
924
-
925
- if(isset($product_cat->name)) {
926
- $catname = $product_cat->name;
927
- $catlink = get_term_link($value,'product_cat');
928
- }
929
- } else {
930
- $product_cat = get_term($value, 'product_cat');
931
- $category_path = WooSEA_Get_Products::woosea_get_term_parents( $product_cat->term_id, 'product_cat', $link = false, $separator = ' / ', $nicename = false, $visited = array() );
932
- $product_data['category_path'] = $category_path;
933
- if(isset($product_cat->name)) {
934
- $catname_concat = $product_cat->name;
935
- $catlink_concat = get_term_link($value,'product_cat');
936
- }
937
- $catname .= "||".$catname_concat;
938
- $catlink .= "||".$catlink_concat;
939
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
940
  }
941
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
942
  } else {
943
  foreach ($categories as $key => $value){
944
- if (!$catname){
945
  $product_cat = get_term($value, 'product_cat');
946
- $category_path = WooSEA_Get_Products::woosea_get_term_parents( $product_cat->term_id, 'product_cat', $link = false, $separator = ' / ', $nicename = false, $visited = array() );
947
- $product_data['category_path'] = $category_path;
 
 
 
 
948
  if(isset($product_cat->name)) {
949
  $catname = $product_cat->name;
950
  $catlink = get_term_link($value,'product_cat');
951
  }
952
  } else {
953
  $product_cat = get_term($value, 'product_cat');
954
- $category_path = WooSEA_Get_Products::woosea_get_term_parents( $product_cat->term_id, 'product_cat', $link = false, $separator = ' / ', $nicename = false, $visited = array() );
955
- $product_data['category_path'] = $category_path;
 
 
 
956
  if(isset($product_cat->name)) {
957
- $catname_concat = $product_cat->name;
958
- $catlink_concat = get_term_link($value,'product_cat');
959
  }
960
  $catname .= "||".$catname_concat;
961
  $catlink .= "||".$catlink_concat;
962
- }
963
  }
964
  }
965
- $product_data['category_link'] = $catlink;
966
- $product_data['categories'] = $catname;
967
- }
968
-
969
- /**
970
- * Get custom and custom product attribute values
971
- */
972
- if (preg_match("/pa_/i", $key)){
973
- $tmp_key = str_replace("pa_", "", $key);
974
- $tmp_key = str_replace("_", " ", $tmp_key);
975
-
976
- $attr_value = $product->get_attribute($tmp_key);
977
-
978
- if(!empty($attr_value)){
979
- $product_data[$key] = $attr_value;
980
- } else {
981
- $product_data[$key] = "";
 
 
 
 
 
 
 
 
982
  }
983
- } elseif (preg_match("/custom_attributes_/i", $key)){
984
- $tmp_key = str_replace("custom_attributes_", "", $key);
985
- $product_data[$key] = $this->get_attribute_value( $this->childID, $tmp_key );
986
  }
987
- }
988
- /**
989
- * Filter execution
990
- */
991
- if (array_key_exists('rules', $project_config)){
992
- $product_data = $this->woocommerce_sea_rules( $project_config['rules'], $product_data );
993
- }
994
 
995
  /**
996
  * Check if we need to add category taxonomy mappings (Google Shopping)
@@ -999,6 +1282,28 @@ class WooSEA_Get_Products {
999
  $product_data = $this->woocommerce_sea_mappings( $project_config['mappings'], $product_data );
1000
  }
1001
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1002
  /**
1003
  * Rules execution
1004
  */
@@ -1082,9 +1387,7 @@ class WooSEA_Get_Products {
1082
 
1083
  $attr_line .= ",'".$shipping_str."'";
1084
  } else {
1085
- if(is_string($product_data[$attr_value['mapfrom']])){
1086
- $attr_line .= ",'".$attr_value['prefix']. "".$product_data[$attr_value['mapfrom']]."" .$attr_value['suffix']."'";
1087
- }
1088
  }
1089
  } else {
1090
  $attr_line .= ",''";
@@ -1146,6 +1449,7 @@ class WooSEA_Get_Products {
1146
  }
1147
  } else {
1148
  foreach($old_attributes_config as $attr_key => $attr_value){
 
1149
  $ca = 0;
1150
  // Static attribute value was set by user
1151
  if(array_key_exists('static_value', $attr_value)){
@@ -1186,9 +1490,7 @@ class WooSEA_Get_Products {
1186
  $ca++;
1187
  $xml_product[$attr_value['attribute']."_$ca"] = "$attr_value[prefix] ". $product_data[$attr_value['mapfrom']] ." $attr_value[suffix]";
1188
  } else {
1189
- if(is_string($product_data[$attr_value['mapfrom']])){
1190
- $xml_product[$attr_value['attribute']] = "$attr_value[prefix] ". $product_data[$attr_value['mapfrom']] ." $attr_value[suffix]";
1191
- }
1192
  }
1193
  }
1194
  }
@@ -1199,7 +1501,7 @@ class WooSEA_Get_Products {
1199
  }
1200
 
1201
  // Do we need to do some calculation on attributes for Google Shopping
1202
- $xml_product = WooSEA_Get_Products::woosea_calculate_value ( $project_config, $xml_product );
1203
 
1204
  foreach($xml_product as $key_product => $value_product){
1205
  if (preg_match("/custom_attributes_attribute_/", $key_product)){
@@ -1228,18 +1530,17 @@ class WooSEA_Get_Products {
1228
  /**
1229
  * Update processing status of project
1230
  */
1231
- $project_updated = WooSEA_Get_Products::woosea_project_update($project_config['project_hash'], $offset_step_size, $xml_piece);
1232
 
1233
  /**
1234
  * Write row to CSV/TXT or XML file
1235
  */
1236
-
1237
  if($project_config['fileformat'] != 'xml'){
1238
  unset($products[0]);
1239
- $file = WooSEA_Get_Products::woosea_create_csvtxt_feed ( array_filter($products), $project_config, 'false' );
1240
  } else {
1241
  if(is_array($xml_piece)){
1242
- $file = WooSEA_Get_Products::woosea_create_xml_feed ( array_filter($xml_piece), $project_config, 'false' );
1243
  unset($xml_piece);
1244
  }
1245
  unset($products);
@@ -1280,8 +1581,14 @@ class WooSEA_Get_Products {
1280
  "Plugin" => WOOCOMMERCESEA_PLUGIN_VERSION
1281
  );
1282
 
 
 
 
 
 
 
1283
  $notifications_obj = new WooSEA_Get_Admin_Notifications;
1284
- $external_debug_file = $notifications_obj->woosea_debug_informations ($versions, $product_numbers, $feed_config);
1285
  // End information for debug log
1286
 
1287
  foreach ( $feed_config as $key => $val ) {
@@ -1368,20 +1675,6 @@ class WooSEA_Get_Products {
1368
  }
1369
  }
1370
 
1371
- /**
1372
- * Make product availability readable
1373
- */
1374
- public function clean_availability( $available ) {
1375
- if ($available) {
1376
- if ($available == 'instock') {
1377
- return "in stock";
1378
- } elseif ($available == 'outofstock') {
1379
- return "out of stock";
1380
- }
1381
- }
1382
- return "out of stock";
1383
- }
1384
-
1385
  /**
1386
  * Calculate the value of an attribute
1387
  */
@@ -1390,10 +1683,10 @@ class WooSEA_Get_Products {
1390
  $xml_product = array_map('trim', $xml_product);
1391
 
1392
  // Check for new products in the Google Shopping feed if we need to 'calculate' the identifier_exists attribute value
1393
- if(($project_config['taxonomy'] == "google_shopping") AND (isset($xml_product['g:condition']))){
1394
  $identifier_exists = "no"; // default value is no
1395
 
1396
- if (array_key_exists("g:brand", $xml_product)){
1397
  // g:gtin exists and has a value
1398
  if ((array_key_exists("g:gtin", $xml_product)) AND ($xml_product['g:gtin'] != "")){
1399
  $identifier_exists = "yes";
@@ -1405,12 +1698,12 @@ class WooSEA_Get_Products {
1405
  $identifier_exists = "no";
1406
  }
1407
  } else {
1408
- // g:gtin exists and has a value
1409
  if ((array_key_exists("g:gtin", $xml_product)) AND ($xml_product['g:gtin'] != "")){
1410
- $identifier_exists = "yes";
1411
- // g:mpn exists and has a value
1412
  } elseif ((array_key_exists("g:mpn", $xml_product)) AND ($xml_product['g:mpn'] != "")){
1413
- $identifier_exists = "yes";
1414
  // g:brand is empty and so are g:gtin and g:mpn, so no identifier exists
1415
  } else {
1416
  $identifier_exists = "no";
@@ -1514,6 +1807,13 @@ class WooSEA_Get_Products {
1514
  $original_cat = $product_data['categories'];
1515
  $original_cat = preg_replace('/&amp;/','&',$original_cat);
1516
 
 
 
 
 
 
 
 
1517
  $tmp_cat = "";
1518
  $match = "false";
1519
 
@@ -1522,66 +1822,34 @@ class WooSEA_Get_Products {
1522
  // Strip slashes
1523
  $pm_array['criteria'] = str_replace("\\","",$pm_array['criteria']);
1524
 
1525
- // Category mapping based on productname
1526
- if($pm_array['attribute'] == "title"){
1527
- if($pm_array['condition'] == "="){
1528
- if($product_data['title'] == $pm_array['criteria']){
1529
- $category_pieces = explode("-", $pm_array['map_to_category']);
1530
- $tmp_cat = $category_pieces[0];
1531
- $match = "true";
1532
- } else {
1533
- $product_data['categories'] = "";
1534
- }
1535
- } elseif ($pm_array['condition'] == "contains"){
1536
- if (@preg_match("/$pm_array[criteria]/i","$product_data[title]")){
1537
- $category_pieces = explode("-", $pm_array['map_to_category']);
1538
- $tmp_cat = $category_pieces[0];
1539
- $match = "true";
1540
- } else {
1541
- $product_data['categories'] = "";
1542
- }
1543
- }
1544
- // Category mapping based on "all products"
1545
- } elseif($pm_array['attribute'] == "all_products") {
1546
- $category_pieces = explode("-", $pm_array['map_to_category']);
1547
- $tmp_cat = $category_pieces[0];
1548
- $match = "true";
1549
- // Category mapping based on category
1550
- } else {
1551
- if($pm_array['condition'] == "="){
1552
- $cat_pieces = explode ("||",$original_cat);
1553
 
1554
- if (count($cat_pieces) > 1){
1555
- foreach ($cat_pieces as $k_piece => $v_piece){
1556
- if($v_piece == $pm_array['criteria']){
1557
- $category_pieces = explode("-", $pm_array['map_to_category']);
1558
- $tmp_cat = $category_pieces[0];
1559
- $match = "true";
1560
- } else {
1561
- $product_data['categories'] = "";
1562
- }
1563
- }
1564
- } else {
1565
- if($original_cat == $pm_array['criteria']){
1566
  $category_pieces = explode("-", $pm_array['map_to_category']);
1567
  $tmp_cat = $category_pieces[0];
1568
  $match = "true";
 
 
1569
  }
1570
  }
1571
- } elseif ($pm_array['condition'] == "contains"){
1572
- if (preg_match("/$pm_array[criteria]/i","$original_cat")){
1573
  $category_pieces = explode("-", $pm_array['map_to_category']);
1574
  $tmp_cat = $category_pieces[0];
1575
  $match = "true";
1576
- } else {
1577
- $product_data['categories'] = "";
1578
  }
1579
  }
1580
  }
1581
  }
1582
-
1583
  if($match == "true"){
1584
  $product_data['categories'] = $tmp_cat;
 
 
1585
  }
1586
 
1587
  return $product_data;
@@ -1857,237 +2125,280 @@ class WooSEA_Get_Products {
1857
  return $product_data;
1858
  }
1859
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1860
  /**
1861
  * Execute project filters (include / exclude)
1862
  */
1863
  private function woocommerce_sea_rules( $project_rules, $product_data ){
1864
- $allowed = "1";
1865
 
1866
- foreach ($project_rules as $pr_key => $pr_array){
 
1867
 
1868
- foreach ($product_data as $pd_key => $pd_value){
 
 
1869
 
1870
- // Check is there is a rule on specific attributes
1871
- if(in_array($pd_key, $pr_array)){
1872
 
1873
- if (is_numeric($pd_value)){
1874
-
1875
- // Rules for numeric values
1876
- switch ($pr_array['condition']) {
1877
- case($pr_array['condition'] = "contains"):
1878
- if ((preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "exclude")){
1879
- $allowed = 0;
1880
- } elseif ((!preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "include_only")){
1881
- $allowed = 0;
1882
- }
1883
- break;
1884
- case($pr_array['condition'] = "containsnot"):
1885
- if ((!preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "exclude")){
1886
- $allowed = 0;
1887
- } elseif ((preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "include_only")){
1888
- $allowed = 0;
1889
- }
1890
- break;
1891
- case($pr_array['condition'] = "="):
1892
- if (($pd_value == $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
1893
- $allowed = 0;
1894
- } elseif (($pd_value != $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
1895
- $allowed = 0;
1896
- }
1897
- break;
1898
- case($pr_array['condition'] = "!="):
1899
- if (($pd_value != $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
1900
- $allowed = 0;
1901
- } elseif (($pd_value == $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
1902
- $allowed = 0;
1903
- }
1904
- break;
1905
- case($pr_array['condition'] = ">"):
1906
- if (($pd_value > $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
1907
- $allowed = 0;
1908
- } elseif (($pd_value <= $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
1909
- $allowed = 0;
1910
- }
1911
- break;
1912
- case($pr_array['condition'] = ">="):
1913
- if (($pd_value >= $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
1914
- $allowed = 0;
1915
- } elseif (($pd_value < $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
1916
- $allowed = 0;
1917
- }
1918
- break;
1919
- case($pr_array['condition'] = "<"):
1920
- if (($pd_value < $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
1921
- $allowed = 0;
1922
- } elseif (($pd_value > $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
1923
- $allowed = 0;
1924
- }
1925
- break;
1926
- case($pr_array['condition'] = "=<"):
1927
- if (($pd_value <= $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
1928
- $allowed = 0;
1929
- } elseif (($pd_value > $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
1930
- $allowed = 0;
1931
- }
1932
- case($pr_array['condition'] = "empty"):
1933
- if ((strlen($pd_value) < 1) && ($pr_array['than'] == "exclude")){
1934
- $allowed = 0;
1935
- } elseif ((strlen($pd_value > 0)) && ($pr_array['than'] == "include_only")){
1936
- $allowed = 0;
1937
- }
1938
- break;
1939
- default:
1940
- break;
1941
  }
1942
- } elseif (is_array($pd_value)){
1943
-
1944
- // For now only shipping details are in an array
1945
- foreach ($pd_value as $k => $v){
1946
- foreach ($v as $kk => $vv){
1947
- // Only shipping detail rule can be on price for now
1948
- if($kk == "price"){
1949
- switch ($pr_array['condition']) {
1950
- case($pr_array['condition'] = "contains"):
1951
- if ((preg_match('/'.$pr_array['criteria'].'/', $vv))){
1952
- $allowed = 0;
1953
- }
1954
- break;
1955
- case($pr_array['condition'] = "containsnot"):
1956
- if ((!preg_match('/'.$pr_array['criteria'].'/', $vv))){
1957
- $allowed = 0;
1958
- }
1959
- break;
1960
- case($pr_array['condition'] = "="):
1961
- if (($vv == $pr_array['criteria'])){
1962
- $allowed = 0;
1963
- }
1964
- break;
1965
- case($pr_array['condition'] = "!="):
1966
- if (($vv != $pr_array['criteria'])){
1967
- $allowed = 0;
1968
- }
1969
- break;
1970
- case($pr_array['condition'] = ">"):
1971
- if (($vv > $pr_array['criteria'])){
1972
- $allowed = 0;
1973
- }
1974
- break;
1975
- case($pr_array['condition'] = ">="):
1976
- if (($vv >= $pr_array['criteria'])){
1977
- $allowed = 0;
1978
- }
1979
- break;
1980
- case($pr_array['condition'] = "<"):
1981
- if (($vv < $pr_array['criteria'])){
1982
- $allowed = 0;
1983
- }
1984
- break;
1985
- case($pr_array['condition'] = "=<"):
1986
- if (($vv <= $pr_array['criteria'])){
1987
- $allowed = 0;
1988
- }
1989
- break;
1990
- case($pr_array['condition'] = "empty"):
1991
- if (strlen($vv) < 1){
1992
- $allowed = 0;
1993
- }
1994
- break;
1995
- default:
1996
- break;
1997
  }
1998
- }
1999
- }
2000
- }
2001
- } else {
2002
- // Rules for string values
2003
-
2004
- // If case-sensitve is off than lowercase both the criteria and attribute value
2005
- if (array_key_exists('cs', $pr_array)){
2006
- if ($pr_array['cs'] != "on"){
2007
- $pd_value = strtolower($pd_value);
2008
- $pr_array['criteria'] = strtolower($pr_array['criteria']);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2009
  }
2010
- }
2011
-
2012
- switch ($pr_array['condition']) {
2013
- case($pr_array['condition'] = "contains"):
2014
- if ((preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "exclude")){
2015
- $allowed = 0;
2016
- } elseif ((!preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "include_only")){
2017
- $allowed = 0;
2018
- }
2019
- break;
2020
- case($pr_array['condition'] = "containsnot"):
2021
- if ((!preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "exclude")){
2022
- $allowed = 0;
2023
- } elseif ((preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "include_only")){
2024
- $allowed = 0;
2025
- }
2026
- break;
2027
- case($pr_array['condition'] = "="):
2028
- if (($pr_array['criteria'] == "$pd_value") && ($pr_array['than'] == "exclude")){
2029
- $allowed = 0;
2030
- } elseif (($pr_array['criteria'] != "$pd_value") && ($pr_array['than'] == "include_only")){
2031
- $allowed = 0;
2032
- }
2033
- break;
2034
- case($pr_array['condition'] = "!="):
2035
- if (($pr_array['criteria'] != "$pd_value") && ($pr_array['than'] == "exclude")){
2036
- $allowed = 0;
2037
- } elseif (($pr_array['criteria'] == "$pd_value") && ($pr_array['than'] == "include_only")){
2038
- $allowed = 0;
2039
- }
2040
- break;
2041
- case($pr_array['condition'] = ">"):
2042
- // Use a lexical order on relational string operators
2043
- if (($pd_value > $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
2044
- $allowed = 0;
2045
- } elseif (($pd_value < $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
2046
- $allowed = 0;
2047
- }
2048
- break;
2049
- case($pr_array['condition'] = ">="):
2050
- // Use a lexical order on relational string operators
2051
- if (($pd_value >= $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
2052
- $allowed = 0;
2053
- } elseif (($pd_value < $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
2054
- $allowed = 0;
2055
- }
2056
- break;
2057
- case($pr_array['condition'] = "<"):
2058
- // Use a lexical order on relational string operators
2059
- if (($pd_value < $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
2060
- $allowed = 0;
2061
- } elseif (($pd_value > $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
2062
- $allowed = 0;
2063
- }
2064
- break;
2065
- case($pr_array['condition'] = "=<"):
2066
- // Use a lexical order on relational string operators
2067
- if (($pd_value <= $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
2068
- $allowed = 0;
2069
- } elseif (($pd_value > $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
2070
- $allowed = 0;
2071
  }
2072
- break;
2073
- case($pr_array['condition'] = "empty"):
2074
- if ((strlen($pd_value) < 1) && ($pr_array['than'] == "exclude")){
2075
- $allowed = 0;
2076
- } elseif ((strlen($pd_value > 0)) && ($pr_array['than'] == "include_only")){
2077
- $allowed = 0;
 
 
 
2078
  }
2079
- break;
2080
- default:
2081
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2082
  }
2083
  }
2084
  }
 
 
 
 
 
2085
  }
2086
  }
 
2087
  if ($allowed < 1){
2088
  $product_data = array();
2089
  $product_data = null;
 
 
2090
  }
2091
- return $product_data;
2092
  }
2093
  }
33
  return $product_cats;
34
  }
35
 
36
+ /**
37
+ * Function to add CDATA brackets to title, short_description and description attributes
38
+ */
39
+ protected function woosea_append_cdata( $string ){
40
+ return $string;
41
+ // return "<![CDATA[ $string ]]>";
42
+ }
43
+
44
  /**
45
  * Function that will create an append with Google Analytics UTM parameters
46
  * Removes UTM paramaters that are left blank
89
  return $utm_part;
90
  }
91
 
92
+ /**
93
+ * Converts an ordinary xml string into a CDATA string
94
+ */
95
+ public function woosea_convert_to_cdata( $string ) {
96
+ return "<![CDATA[ $string ]]>";
97
+ }
98
+
99
+ /**
100
+ * Get custom attribute names for a product
101
+ */
102
+ private function get_custom_attributes( $productId ) {
103
+ global $wpdb;
104
+ $list = array();
105
+
106
+ $sql = "SELECT meta_key as name, meta_value as type FROM " . $wpdb->prefix . "postmeta" . " WHERE post_id=".$productId." group by meta_key";
107
+ $data = $wpdb->get_results($sql);
108
+
109
+ if (count($data)) {
110
+ foreach ($data as $key => $value) {
111
+ $value_display = str_replace("_", " ",$value->name);
112
+ if (!preg_match("/pyre|sbg/i",$value->name)){
113
+ $list[$value->name] = ucfirst($value_display);
114
+ }
115
+ }
116
+ return $list;
117
+ }
118
+ return false;
119
+ }
120
+
121
+ /**
122
+ * Get orders for given time period used in filters
123
+ */
124
+ public function woosea_get_orders( $project_config ){
125
+ $query_args = array(
126
+ 'post_type' => wc_get_order_types(),
127
+ 'post_status' => array_keys( wc_get_order_statuses() ),
128
+ 'posts_per_page' => 999999999999,
129
+ );
130
+ $all_orders = get_posts( $query_args );
131
+
132
+ foreach ( $all_orders as $orders ) {
133
+ $order = wc_get_order( $orders-> ID);
134
+ $order_data = $order->get_data();
135
+ $order_date_created = $order_data['date_created']->date('Y-m-d H:i:s');
136
+
137
+ //error_log("ORDER ID:" . $orders->ID);
138
+ //error_log("ORDER DATE:" . $order_date_created);
139
+
140
+ foreach ($order->get_items() as $item_key => $item_values){
141
+ $product_id = $item_values->get_product_id();
142
+ //error_log("PRODUCT ID:" . $product_id);
143
+ }
144
+ }
145
+ //return $orders_timeframe;
146
+ }
147
+
148
  /**
149
  * Get category path (needed for Prisjakt)
150
  */
151
+ public function woosea_get_term_parents( $id, $taxonomy, $link = false, $project_taxonomy, $nicename = false, $visited = array() ) {
152
+ // Only add Home to the beginning of the chain when we start buildin the chain
153
+ if(empty($visited)){
154
+ $chain = 'Home';
155
+ } else {
156
+ $chain = '';
157
+ }
158
+
159
  $parent = get_term( $id, $taxonomy );
160
+ $separator = ' &gt; ';
161
+
162
+ if( $project_taxonomy == "Prisjakt" ){
163
+ $separator = ' / ';
164
+ }
165
+
166
  if ( is_wp_error( $parent ) )
167
  return $parent;
168
 
174
 
175
  if ($parent->parent && ( $parent->parent != $parent->term_id ) && !in_array( $parent->parent, $visited )){
176
  $visited[] = $parent->parent;
177
+ $chain .= $this->woosea_get_term_parents( $parent->parent, $taxonomy, $link, $separator, $nicename, $visited );
178
  }
179
 
180
  if ($link){
181
+ $chain .= $separator.$name;
182
  } else {
183
+ $chain .= $separator.$name;
184
  }
185
  return $chain;
186
  } // End woo_get_term_parents()
209
  $base_country = $base_location['country'];
210
 
211
  foreach ( $shipping_zones as $zone){
212
+
213
  $zone_details = array();
214
  $zone_code = $zone['zone_locations'][0]->code;
215
  $zone_details['country'] = $zone_code;
218
  if(isset($zone['zone_locations'][1]->code)){
219
  $zone_region = $zone['zone_locations'][1]->code;
220
  $zn_short = explode (":", $zone_region);
221
+
222
+ if(count($zn_short) > 1){
223
+ $zone_details['region'] = $zn_short[1];
224
+ }
225
  }
226
 
227
  // When no shipping zone has been configured in project take the shops country zone id as default
234
 
235
  foreach ( $arr_shipping_methods as $shipping ) {
236
 
 
237
  // FLAT RATE SHIPPING COSTS
238
+ //if($shipping['instance_settings']['title'] == "Flat rate"){
239
  if(isset($shipping['instance_settings']['cost'])){
240
  $zone_details['service'] = $shipping['instance_settings']['title'];
241
  $shipping_cost = $shipping['instance_settings']['cost'];
246
  $zone_details['service'] = $shipping['instance_settings']['title'];
247
  $shipping_cost = ($shipping['instance_settings'][$class_cost_id]+$shipping_cost);
248
  }
249
+ //}
250
 
251
  // FREE SHIPPING COSTS
252
  if($shipping['instance_settings']['title'] == "Free shipping"){
258
  }
259
 
260
  foreach ($tax_rates as $k => $v){
261
+ if((isset($v['shipping'])) and ($v['shipping'] == "yes")){
262
  $rate = (($v['rate']+100)/100);
263
  $shipping_cost = $shipping_cost*$rate;
264
  $shipping_cost = round($shipping_cost, 2);
344
 
345
  // Some channels need their own feed config and XML namespace declarations (such as Google shopping)
346
  if ($feed_config['taxonomy'] == 'google_shopping'){
347
+ $namespace = array( 'g' => 'http://base.google.com/ns/1.0' );
 
 
348
  if ( ($header == "true") AND ($feed_config['nr_products_processed'] == 0) ) {
349
+ $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><rss xmlns:g="http://base.google.com/ns/1.0"></rss>');
350
  $xml->addAttribute('version', '2.0');
351
  $xml->addChild('channel');
352
+ $xml->channel->addChild('title', $feed_config['projectname'] );
353
  $xml->channel->addChild('link', site_url());
354
  $xml->channel->addChild('description', 'WooCommerce Product Feed PRO - This product feed is created with the free Advanced WooCommerce Product Feed PRO plugin from AdTribes.io. For all your support questions check out our FAQ on https://www.adtribes.io or e-mail to: support@adtribes.io ');
355
  $xml->asXML($file);
357
  $xml = simplexml_load_file($file, 'SimpleXMLElement', LIBXML_NOCDATA);
358
  $aantal = count($products);
359
 
360
+ if ($xml === FALSE){
361
+ // Something went wrong reading the XML file
362
+ } else {
363
+ if ($aantal > 0){
364
+ foreach ($products as $key => $value){
365
+
366
+ if (is_array ( $value ) ) {
367
+
368
+ if(!empty( $value )){
369
+ $product = $xml->channel->addChild('item');
370
+ foreach ($value as $k => $v){
371
+ if ($k == "g:shipping"){
372
+ $ship = explode("||", $v);
373
+ foreach ($ship as $kk => $vv){
374
+ $country_ship = explode(":", $vv);
375
 
376
+ $shipping = $product->addChild($k, '', $namespace['g']);
377
+ $shipping_country = $shipping->addChild('g:country', $country_ship[0], $namespace['g']);
378
+ $shipping_region = $shipping->addChild('g:region', $country_ship[2], $namespace['g']);
379
+ $shipping_service = $shipping->addChild('g:service', $country_ship[1], $namespace['g']);
380
+ $shipping_price = $shipping->addChild('g:price', $country_ship[3], $namespace['g']);
381
+ }
382
+ // Fix issue with additional images for Google Shopping
383
+ } elseif (preg_match("/g:additional_image_link/i",$k)){
384
+ $link = $product->addChild('g:additional_image_link', $v, $namespace['g']);
385
+ //$product->$k = $v;
386
+ } else {
387
+ $product->$k = $v;
388
+ }
389
  }
 
 
 
 
 
 
390
  }
391
+ }
392
+ }
393
  }
 
 
394
  }
395
+ $xml->asXML($file);
396
  unset($products);
397
  }
398
  unset($xml);
436
  $xml->asXML($file);
437
  } elseif ($feed_config['name'] == "Heureka.cz") {
438
  $xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><SHOP></SHOP>');
439
+ $xml->addAttribute('xmlns', 'https://www.zbozi.cz/ns/offer/1.0');
440
  $xml->asXML($file);
441
  } else {
442
  $xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><products></products>');
546
  // Do not add these nodes to Yandex product feeds
547
  } else {
548
  if ($feed_config['fields'] != 'standard'){
549
+ $k = $this->get_alternative_key ($channel_attributes, $k);
550
  }
551
 
552
  if(!empty($k)){
589
 
590
  // Check if file exists, if it does: delete it first so we can create a new updated one
591
  if ( (file_exists( $file )) AND ($feed_config['nr_products_processed'] == 0) AND ($header == "true") ) {
592
+ @unlink ( $file );
593
  }
594
 
595
  // Check if there is a channel feed class that we need to use
616
 
617
  foreach ($pieces as $k => $v){
618
  if ($feed_config['fields'] != 'standard'){
619
+ $v = $this->get_alternative_key ($channel_attributes, $v);
620
  }
621
 
622
  // For CSV fileformat the keys need to get stripped of the g:
626
 
627
  $pieces[$k] = $v;
628
  }
629
+
630
+ // Convert tab delimiter
631
+ if($feed_config['delimiter'] == "tab"){
632
+ $csv_delimiter = "\t";
633
+ } else {
634
+ $csv_delimiter = $feed_config['delimiter'];
635
+ }
636
+ $blaat = fputcsv($fp, $pieces, $csv_delimiter, '"');
637
  }
638
  }
639
  // Close the file
668
  "Plugin" => WOOCOMMERCESEA_PLUGIN_VERSION
669
  );
670
 
671
+ /**
672
+ * Function for checking if license is valid
673
+ */
674
+ if (!wp_next_scheduled( 'woosea_check_license' ) ) {
675
+ wp_schedule_event ( time(), 'twicedaily', 'woosea_check_license');
676
+ }
677
+
678
+
679
  /**
680
  * Do not change these settings, they are here to prevent running into memory issues
681
  */
686
  // Old version, process a maximum of 100 products per batch
687
  $nr_batches = ceil($published_products/200);
688
  } else {
689
+ // Fast PHP version, process a 750 products per batch
690
+ $nr_batches = ceil($published_products/750);
691
+
692
+ if($published_products > 50000){
693
+ $nr_batches = ceil($published_products/1500);
694
+ } else {
695
+ $nr_batches = ceil($published_products/750);
696
+ }
697
  }
698
  $offset_step_size = ceil($published_products/$nr_batches);
699
 
732
  $attr = trim($attr, "'");
733
  $products[] = array ( $attr );
734
  if($nr_products_processed == 0){
735
+ $file = $this->woosea_create_csvtxt_feed ( $products, $project_config, 'true' );
736
  }
737
  } else {
738
  $products[] = array ();
739
+ $file = $this->woosea_create_xml_feed ( $products, $project_config, 'true' );
740
  }
741
  $xml_piece = "";
742
 
747
  $post_type = array('product');
748
  }
749
 
750
+ // Get Orders
751
+ // $order_timeframe = WooSEA_Get_Products::woosea_get_orders ( $project_config );
752
+
753
  // Construct WP query
754
  $wp_query = array(
755
  'posts_per_page' => $offset_step_size,
769
  // Log the query output for debugging purposes
770
  // $log_query = WooSEA_Get_Products::woosea_create_query_log($prods, "query_output");
771
 
772
+ $shipping_zones = $this->woosea_get_shipping_zones();
773
 
774
  while ($prods->have_posts()) : $prods->the_post();
775
  global $product;
791
  $product_data['title'] = $product->get_title();
792
  $product_data['sku'] = $product->get_sku();
793
  $product_data['sku_id'] = $product_data['id'];
794
+ $product_data['publication_date'] = get_the_date('d-m-y G:i:s');
795
+
796
  if (!empty($product_data['sku'])){
797
  $product_data['sku_id'] = $product_data['sku']."_".$product_data['id'];
798
  }
805
 
806
  $product_id = $product_data['id'];
807
  $primary_cat_id=get_post_meta($product_id ,'_yoast_wpseo_primary_product_cat',true);
808
+ $category_path = $this->woosea_get_term_parents( $primary_cat_id, 'product_cat', $link = false, $project_taxonomy = $project_config['taxonomy'], $nicename = false, $visited = array() );
809
+
810
+ if(!is_object($category_path)){
811
+ $product_data['category_path'] = $category_path;
812
+ }
813
+
814
  if(($primary_cat_id) AND ($primary_cat_id > 0)){
815
  $product_cat = get_term($primary_cat_id, 'product_cat');
816
 
846
 
847
  // Check if there are mother categories
848
  $parent_categories = get_ancestors($product_cat->term_id, 'product_cat');
849
+ $category_path = $this->woosea_get_term_parents( $product_cat->term_id, 'product_cat', $link = false, $project_taxonomy = $project_config['taxonomy'], $nicename = false, $visited = array() );
850
+
851
+ if(!is_object($category_path)){
852
+ $product_data['category_path'] = $category_path;
853
+ }
854
 
855
  foreach ($parent_categories as $category_id){
856
  $parent = get_term_by('id', $category_id, 'product_cat');
864
  } else {
865
  $product_cat = get_term($value, 'product_cat');
866
 
867
+ $category_path = $this->woosea_get_term_parents( $product_cat->term_id, 'product_cat', $link = false, $project_taxonomy = $project_config['taxonomy'], $nicename = false, $visited = array() );
868
+ if(!is_object($category_path)){
869
+ $product_data['category_path'] = $category_path;
870
+ }
871
+
872
  // Check if there are mother categories
873
  $parent_categories = get_ancestors($product_cat->term_id, 'product_cat');
874
+
875
  foreach ($parent_categories as $category_id){
876
  $parent = get_term_by('id', $category_id, 'product_cat');
877
+ $parent_name = "||".$parent->name;
878
  }
879
 
880
  if(isset($product_cat->name)) {
888
  }
889
 
890
  $product_data['category_link'] = $catlink;
891
+ $product_data['raw_categories'] = $catname;
892
  $product_data['categories'] = $catname;
893
+ $product_data['description'] = html_entity_decode((str_replace("\r", "", $post->post_content)), ENT_QUOTES | ENT_XML1, 'UTF-8');
894
+ $product_data['short_description'] = html_entity_decode((str_replace("\r", "", $post->post_excerpt)), ENT_QUOTES | ENT_XML1, 'UTF-8');
895
 
896
  // Strip HTML from (short) description
897
  $product_data['description'] = strip_shortcodes(strip_tags($product_data['description']));
898
  $product_data['short_description'] = strip_shortcodes(strip_tags($product_data['short_description']));
899
 
900
+ // Strip out the non-line-brake character
901
+ $product_data['description'] = str_replace("&#xa0;", "", $product_data['description']);
902
+ $product_data['short_description'] = str_replace("&#xa0;", "", $product_data['short_description']);
903
+
904
  /**
905
  * Check of we need to add Google Analytics UTM parameters
906
  */
907
+ if(isset($project_config['utm_on'])){
908
+ $utm_part = $this->woosea_append_utm_code ( $project_config, get_the_ID(), $this->parentID);
909
+ } else {
910
+ $utm_part = "";
911
+ }
912
 
913
  $product_data['link'] = get_permalink()."$utm_part";
914
+ $product_data['condition'] = ucfirst( get_post_meta( $product_data['id'], '_woosea_condition', true ) );
915
+ if(empty($product_data['condition'])){
916
+ $product_data['condition'] = "New";
917
+ }
918
+
919
  $product_data['availability'] = $this->get_stock( $this->childID );
920
+
921
+ /**
922
+ * When 'Enable stock management at product level is active
923
+ * availability will always return out of stock, even when the stock quantity > 0
924
+ * Therefor, we need to check the stock_status and overwrite te availability value
925
+ */
926
+ $stock_status = $product->get_stock_status();
927
+ if ($stock_status == "outofstock"){
928
+ $product_data['availability'] = "out of stock";
929
+ } else {
930
+ $product_data['availability'] = "in stock";
931
+ }
932
+
933
  $product_data['quantity'] = $this->clean_quantity( $this->childID, "_stock" );
934
  $product_data['visibility'] = $this->get_attribute_value( $this->childID,"_visibility" );
935
  $product_data['currency'] = get_woocommerce_currency();
936
  $product_data['sale_price_start_date'] = $this->get_sale_date($this->childID, "_sale_price_dates_from");
937
  $product_data['sale_price_end_date'] = $this->get_sale_date($this->childID, "_sale_price_dates_to");
938
+ $product_data['sale_price_effective_date'] = $product_data['sale_price_start_date'] ."/".$product_data['sale_price_end_date'];
939
  $product_data['image'] = wp_get_attachment_url($product->get_image_id());
 
940
  $gallery_ids = $product->get_gallery_image_ids();
941
  foreach ($gallery_ids as $gallery_key => $gallery_value){
942
  $gal_id = $gallery_key+1;
956
  $product_data['regular_price'] = wc_format_localized_price(wc_get_price_including_tax($product, array('price'=> $product->get_regular_price())));
957
  $product_data['sale_price'] = wc_format_localized_price(wc_get_price_including_tax($product, array('price'=> $product->get_sale_price())));
958
 
959
+ // Workaround for price caching issues
960
+ if(!isset($tax_rates[1]['rate'])){
961
+ $tax_rates[1]['rate'] = 0;
962
+ }
963
+
964
+ $product_data['price_forced'] = round(wc_format_localized_price( wc_get_price_excluding_tax($product,array('price'=> $product->get_price())) * (100+$tax_rates[1]['rate'])/100 ), 2);
965
+ $product_data['regular_price_forced'] = round(wc_format_localized_price(wc_get_price_excluding_tax($product, array('price'=> $product->get_regular_price())) + (100+$tax_rates[1]['rate'])/100 ), 2);
966
+ $product_data['sale_price_forced'] = round(wc_format_localized_price(wc_get_price_excluding_tax($product, array('price'=> $product->get_sale_price())) + (100+$tax_rates[1]['rate'])/100 ), 2);
967
+
968
  // Get net prices
969
  $product_data['net_price'] = wc_format_localized_price($product->get_price());
970
  $product_data['net_regular_price'] = wc_format_localized_price($product->get_regular_price());
974
  if($product_data['sale_price'] > 0){
975
  $price = $product_data['sale_price'];
976
  }
977
+
978
+ $product_data['shipping'] = $this->woosea_get_shipping_cost($class_cost_id, $project_config, $price, $tax_rates, $shipping_zones);
979
 
980
  $shipping_str = "";
981
  foreach ($product_data['shipping'] as $key => $value){
1003
  * Do we need to add Dynamic Attributes?
1004
  */
1005
  $project_config['attributes_original'] = $project_config['attributes'];
1006
+
1007
  if($project_config['fields'] != 'standard'){
1008
  //$project_config['attributes_original'] = array();
1009
  foreach($project_config['attributes'] as $stand_key => $stand_val){
1012
  }
1013
  }
1014
  }
1015
+
1016
+ $no_taxonomies = array("element_category","template_category","portfolio_category","portfolio_skills","portfolio_tags","faq_category","slide-page","yst_prominent_words","category","post_tag","nav_menu","link_category","post_format","product_type","product_visibility","product_cat","product_shipping_class","product_tag");
1017
+ $taxonomies = get_taxonomies();
1018
+
1019
+ $diff_taxonomies = array_diff($taxonomies, $no_taxonomies);
1020
+
1021
+ foreach($diff_taxonomies as $taxo){
1022
+ $term_value = get_the_terms($product_data['id'], $taxo);
1023
+
1024
+ if(is_array($term_value)){
1025
+ foreach($term_value as $term){
1026
+ $product_data[$taxo] = $term->name;
1027
+ }
1028
+ }
1029
+ }
1030
+
1031
+ /**
1032
+ * Get Custom Attributes for Single products
1033
+ */
1034
+ if ($product->is_type('simple')){
1035
+
1036
+ $custom_attributes = $this->get_custom_attributes( $product_data['id'] );
1037
+
1038
+ foreach($custom_attributes as $custom_kk => $custom_vv){
1039
+ $custom_value = get_post_meta( $product_data['id'], $custom_kk, true );
1040
+ $new_key ="custom_attributes_" . $custom_kk;
1041
+
1042
+ // Just to make sure product names are never empty
1043
+ if(($custom_kk == "_woosea_optimized_title") && ($custom_value == "")){
1044
+ $custom_value = $product_data['title'];
1045
+ }
1046
+
1047
+ // Just to make sure the condition field is never empty
1048
+ if(($custom_kk == "_woosea_condition") && ($custom_value == "")){
1049
+ $custom_value = $product_data['condition'];
1050
+ }
1051
+
1052
+
1053
+ if(!empty( $custom_value )){
1054
+
1055
+ // Need to clean up the strange price rightpress is returning
1056
+ if($custom_kk == "rp_wcdpd_price_cache"){
1057
+
1058
+ $product_data['price'] = $custom_value['price']['p'];
1059
+ $product_data['sale_price'] = $custom_value['sale_price']['p'];
1060
+ }
1061
+
1062
+ $product_data[$new_key] = $custom_value;
1063
+ }
1064
+ }
1065
+ }
1066
 
1067
  /**
1068
+ * Get Product Attributes for Single products
1069
  */
1070
  if ($product->is_type('simple')){
1071
  $single_attributes = $product->get_attributes();
1076
  $product_data[$attr_name] = $attr_value;
1077
  }
1078
  }
1079
+
1080
  /**
1081
+ * Versioned products need a seperate approach
1082
+ * Get data for these products based on the mother products item group id
1083
  */
1084
+ if( ($product_data['item_group_id'] > 0) ){
 
 
 
 
 
 
 
 
1085
 
1086
+ $product_variations = new WC_Product_Variation( $product_data['id'] );
1087
+ $variations = $product_variations->get_variation_attributes();
1088
+ $append = "";
1089
+
1090
+ /**
1091
+ * Although this is a product variation we also need to grap the Product attributes belonging to the simple mother product
1092
+ */
1093
+ $mother_attributes = get_post_meta($product_data['item_group_id'], '_product_attributes');
1094
+ foreach ($mother_attributes as $attribute){
1095
+ foreach($attribute as $attr){
1096
 
1097
+ $attr_name = $attr['name'];
1098
+ $terms = get_the_terms($product_data['item_group_id'], $attr_name);
1099
+
1100
+ if(is_array($terms)){
1101
+
1102
+ foreach($terms as $term){
1103
+ $attr_value = $term->name;
1104
  }
1105
+ $product_data[$attr_name] = $attr_value;
1106
+ }
1107
+ }
1108
+ }
1109
 
1110
+
1111
+ /**
1112
+ * Although this is a product variation we also need to grap the Dynamic attributes belonging to the simple mother prodict
1113
+ */
1114
+ foreach($diff_taxonomies as $taxo){
1115
+ $term_value = get_the_terms($product_data['item_group_id'], $taxo);
1116
+
1117
+ if(is_array($term_value)){
1118
+ foreach($term_value as $term){
1119
+ $product_data[$taxo] = $term->name;
1120
+ }
1121
+ }
1122
+ }
1123
+
1124
+ // User does need to also add the attributes to the feed otherwise they cannot be appended to the productname
1125
+ foreach($variations as $kk => $vv){
1126
+ $custom_key = $kk;
1127
+
1128
+ if (isset($project_config['product_variations']) AND ($project_config['product_variations'] == "on")){
1129
+ $taxonomy = str_replace("attribute_","",$kk);
1130
+ $term = get_term_by('slug', $vv, $taxonomy);
1131
+
1132
+ if($term){
1133
+ $append = ucfirst($term->name);
1134
  }
1135
+
1136
+ // Prevent duplicate attribute values from being added to the product name
1137
+ //if(!preg_match('/'.$product_data['title'].'/', $append)){
1138
+ // $product_data['title'] = $product_data['title']." ".$append;
1139
+ //}
1140
  }
1141
+
1142
+ $custom_key = str_replace("attribute_","",$custom_key);
1143
+ $product_data[$custom_key] = $vv;
1144
+ $append = "";
1145
+ }
1146
+
1147
+ /**
1148
+ * Get Custom Attributes for this variable product
1149
+ */
1150
+ $custom_attributes = $this->get_custom_attributes( $product_data['id'] );
1151
+
1152
+ foreach($custom_attributes as $custom_kk => $custom_vv){
1153
+ $custom_value = get_post_meta( $product_data['id'], $custom_kk, true );
1154
+
1155
+ // Product variant brand is empty, grap that of the mother product
1156
+ if(($custom_kk == "_woosea_brand") && ($custom_value == "")){
1157
+ $custom_value = get_post_meta( $product_data['item_group_id'], $custom_kk, true );
1158
+ }
1159
+
1160
+ // Product variant optimized title is empty, grap the mother product title
1161
+ if(($custom_kk == "_woosea_optimized_title") && ($custom_value == "")){
1162
+ $custom_value = $product_data['title'];
1163
+ }
1164
+
1165
+ if(!is_array($custom_value)){
1166
+
1167
+ $new_key ="custom_attributes_" . $custom_kk;
1168
+ // In order to make the mapping work again, replace var by product
1169
+ $new_key = str_replace("var","product",$new_key);
1170
+ if(!empty( $custom_value )){
1171
+ $product_data[$new_key] = $custom_value;
1172
+ }
1173
+ }
1174
+ }
1175
+
1176
+ /**
1177
+ * We also need to make sure that we get the custom attributes belonging to the simple mother product
1178
+ */
1179
+ $custom_attributes_mother = $this->get_custom_attributes( $product_data['item_group_id'] );
1180
+
1181
+ foreach($custom_attributes_mother as $custom_kk_m => $custom_value_m){
1182
+ if(!array_key_exists($custom_kk_m, $product_data)){
1183
+ $custom_value_m = get_post_meta( $product_data['item_group_id'], $custom_kk_m, true );
1184
+ $new_key_m ="custom_attributes_" . $custom_kk_m;
1185
+ // In order to make the mapping work again, replace var by product
1186
+ $new_key_m = str_replace("var","product",$new_key_m);
1187
+
1188
+ if(!key_exists($new_key_m, $product_data) AND (!empty($custom_value_m))){
1189
+ if(!is_array($custom_value_m)){
1190
+ // determine what to do with this later
1191
+ } else {
1192
+ $product_data[$new_key_m] = $custom_value_m;
1193
  }
1194
  }
1195
+ }
1196
+ }
1197
+
1198
+ // Get versioned product categories
1199
+ $categories = wc_get_product_cat_ids( $product_data['item_group_id'] );
1200
+
1201
+ // Check if the Yoast plugin is installed and active
1202
+ if ( class_exists('WPSEO_Primary_Term') ){
1203
+ $product_id = $product_data['item_group_id'];
1204
+
1205
+ $primary_cat_id=get_post_meta($product_id ,'_yoast_wpseo_primary_product_cat',true);
1206
+ if($primary_cat_id){
1207
+ $product_cat = get_term($primary_cat_id, 'product_cat');
1208
+ $category_path = $this->woosea_get_term_parents( $product_cat->term_id, 'product_cat', $link = false, $project_taxonomy = $project_config['taxonomy'], $nicename = false, $visited = array() );
1209
+ if(!is_object($category_path)){
1210
+ $product_data['category_path'] = $category_path;
1211
+ }
1212
+
1213
+ if(isset($product_cat->name)) {
1214
+ $catname = $product_cat->name;
1215
+ $catlink = get_category_link($product_cat->term_id);
1216
+ }
1217
  } else {
1218
  foreach ($categories as $key => $value){
1219
+ if (!$catname){
1220
  $product_cat = get_term($value, 'product_cat');
1221
+ $category_path = $this->woosea_get_term_parents( $product_cat->term_id, 'product_cat', $project_taxonomy = $project_config['taxonomy'], $link = false, $nicename = false, $visited = array() );
1222
+
1223
+ if(!is_object($category_path)){
1224
+ $product_data['category_path'] = $category_path;
1225
+ }
1226
+
1227
  if(isset($product_cat->name)) {
1228
  $catname = $product_cat->name;
1229
  $catlink = get_term_link($value,'product_cat');
1230
  }
1231
  } else {
1232
  $product_cat = get_term($value, 'product_cat');
1233
+ $category_path = $this->woosea_get_term_parents( $product_cat->term_id, 'product_cat', $link = false, $project_taxonomy = $project_config['taxonomy'], $nicename = false, $visited = array() );
1234
+ if(!is_object($category_path)){
1235
+ $product_data['category_path'] = $category_path;
1236
+ }
1237
+
1238
  if(isset($product_cat->name)) {
1239
+ $catname_concat = $product_cat->name;
1240
+ $catlink_concat = get_term_link($value,'product_cat');
1241
  }
1242
  $catname .= "||".$catname_concat;
1243
  $catlink .= "||".$catlink_concat;
1244
+ }
1245
  }
1246
  }
1247
+ } else {
1248
+ foreach ($categories as $key => $value){
1249
+ if (!$catname){
1250
+ $product_cat = get_term($value, 'product_cat');
1251
+ $category_path = $this->woosea_get_term_parents( $product_cat->term_id, 'product_cat', $link = false, $project_taxonomy = $project_config['taxonomy'], $nicename = false, $visited = array() );
1252
+ if(!is_object($category_path)){
1253
+ $product_data['category_path'] = $category_path;
1254
+ }
1255
+ if(isset($product_cat->name)) {
1256
+ $catname = $product_cat->name;
1257
+ $catlink = get_term_link($value,'product_cat');
1258
+ }
1259
+ } else {
1260
+ $product_cat = get_term($value, 'product_cat');
1261
+ $category_path = $this->woosea_get_term_parents( $product_cat->term_id, 'product_cat', $link = false, $project_taxonomy = $project_config['taxonomy'], $nicename = false, $visited = array() );
1262
+ if(!is_object($category_path)){
1263
+ $product_data['category_path'] = $category_path;
1264
+ }
1265
+ if(isset($product_cat->name)) {
1266
+ $catname_concat = $product_cat->name;
1267
+ $catlink_concat = get_term_link($value,'product_cat');
1268
+ }
1269
+ $catname .= "||".$catname_concat;
1270
+ $catlink .= "||".$catlink_concat;
1271
+ }
1272
  }
 
 
 
1273
  }
1274
+ $product_data['category_link'] = $catlink;
1275
+ $product_data['categories'] = $catname;
1276
+ }
 
 
 
 
1277
 
1278
  /**
1279
  * Check if we need to add category taxonomy mappings (Google Shopping)
1282
  $product_data = $this->woocommerce_sea_mappings( $project_config['mappings'], $product_data );
1283
  }
1284
 
1285
+
1286
+ /**
1287
+ * In order to prevent XML formatting errors in Google's Merchant center
1288
+ * we will add CDATA brackets to the title and description attributes
1289
+ */
1290
+ $product_data['title'] = $this->woosea_append_cdata ( $product_data['title'] );
1291
+ $product_data['description'] = $this->woosea_append_cdata ( $product_data['description'] );
1292
+ $product_data['short_description'] = $this->woosea_append_cdata ( $product_data['short_description'] );
1293
+
1294
+
1295
+ /**
1296
+ * Check if individual products need to be excluded
1297
+ */
1298
+ $product_data = $this->woosea_exclude_individual( $product_data );
1299
+
1300
+ /**
1301
+ * Filter execution
1302
+ */
1303
+ if (array_key_exists('rules', $project_config)){
1304
+ $product_data = $this->woocommerce_sea_rules( $project_config['rules'], $product_data );
1305
+ }
1306
+
1307
  /**
1308
  * Rules execution
1309
  */
1387
 
1388
  $attr_line .= ",'".$shipping_str."'";
1389
  } else {
1390
+ $attr_line .= ",'".$attr_value['prefix']. "".$product_data[$attr_value['mapfrom']]."" .$attr_value['suffix']."'";
 
 
1391
  }
1392
  } else {
1393
  $attr_line .= ",''";
1449
  }
1450
  } else {
1451
  foreach($old_attributes_config as $attr_key => $attr_value){
1452
+
1453
  $ca = 0;
1454
  // Static attribute value was set by user
1455
  if(array_key_exists('static_value', $attr_value)){
1490
  $ca++;
1491
  $xml_product[$attr_value['attribute']."_$ca"] = "$attr_value[prefix] ". $product_data[$attr_value['mapfrom']] ." $attr_value[suffix]";
1492
  } else {
1493
+ $xml_product[$attr_value['attribute']] = "$attr_value[prefix] ". $product_data[$attr_value['mapfrom']] ." $attr_value[suffix]";
 
 
1494
  }
1495
  }
1496
  }
1501
  }
1502
 
1503
  // Do we need to do some calculation on attributes for Google Shopping
1504
+ $xml_product = $this->woosea_calculate_value ( $project_config, $xml_product );
1505
 
1506
  foreach($xml_product as $key_product => $value_product){
1507
  if (preg_match("/custom_attributes_attribute_/", $key_product)){
1530
  /**
1531
  * Update processing status of project
1532
  */
1533
+ $project_updated = $this->woosea_project_update($project_config['project_hash'], $offset_step_size, $xml_piece);
1534
 
1535
  /**
1536
  * Write row to CSV/TXT or XML file
1537
  */
 
1538
  if($project_config['fileformat'] != 'xml'){
1539
  unset($products[0]);
1540
+ $file = $this->woosea_create_csvtxt_feed ( array_filter($products), $project_config, 'false' );
1541
  } else {
1542
  if(is_array($xml_piece)){
1543
+ $file = $this->woosea_create_xml_feed ( array_filter($xml_piece), $project_config, 'false' );
1544
  unset($xml_piece);
1545
  }
1546
  unset($products);
1581
  "Plugin" => WOOCOMMERCESEA_PLUGIN_VERSION
1582
  );
1583
 
1584
+ // Get the sales from created product feeds
1585
+ global $wpdb;
1586
+ $charset_collate = $wpdb->get_charset_collate();
1587
+ $table_name = $wpdb->prefix . 'adtribes_my_conversions';
1588
+ $order_rows = $wpdb->get_results("SELECT * FROM $table_name", ARRAY_A);
1589
+
1590
  $notifications_obj = new WooSEA_Get_Admin_Notifications;
1591
+ $external_debug_file = $notifications_obj->woosea_debug_informations ($versions, $product_numbers, $order_rows, $feed_config);
1592
  // End information for debug log
1593
 
1594
  foreach ( $feed_config as $key => $val ) {
1675
  }
1676
  }
1677
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1678
  /**
1679
  * Calculate the value of an attribute
1680
  */
1683
  $xml_product = array_map('trim', $xml_product);
1684
 
1685
  // Check for new products in the Google Shopping feed if we need to 'calculate' the identifier_exists attribute value
1686
+ if(($project_config['taxonomy'] == "google_shopping") AND (isset($xml_product['g:condition'])) AND (!isset($xml_product['g:identifier_exists']))){
1687
  $identifier_exists = "no"; // default value is no
1688
 
1689
+ if (array_key_exists("g:brand", $xml_product) AND ($xml_product['g:brand'] != "")){
1690
  // g:gtin exists and has a value
1691
  if ((array_key_exists("g:gtin", $xml_product)) AND ($xml_product['g:gtin'] != "")){
1692
  $identifier_exists = "yes";
1698
  $identifier_exists = "no";
1699
  }
1700
  } else {
1701
+ // g:gtin exists and has a value but brand is empty
1702
  if ((array_key_exists("g:gtin", $xml_product)) AND ($xml_product['g:gtin'] != "")){
1703
+ $identifier_exists = "no";
1704
+ // g:mpn exists and has a value but brand is empty
1705
  } elseif ((array_key_exists("g:mpn", $xml_product)) AND ($xml_product['g:mpn'] != "")){
1706
+ $identifier_exists = "no";
1707
  // g:brand is empty and so are g:gtin and g:mpn, so no identifier exists
1708
  } else {
1709
  $identifier_exists = "no";
1807
  $original_cat = $product_data['categories'];
1808
  $original_cat = preg_replace('/&amp;/','&',$original_cat);
1809
 
1810
+ // When a product sits in multiple categories we use the last category to map on
1811
+ if (strpos($original_cat, '||') !== false) {
1812
+ $original_cat_pieces = explode("||", $original_cat);
1813
+ $nr_pieces = count($original_cat_pieces);
1814
+ $original_cat = $original_cat_pieces[$nr_pieces-1];
1815
+ }
1816
+
1817
  $tmp_cat = "";
1818
  $match = "false";
1819
 
1822
  // Strip slashes
1823
  $pm_array['criteria'] = str_replace("\\","",$pm_array['criteria']);
1824
 
1825
+ // First check if there is a category mapping for this specific product
1826
+ if(($pm_array['criteria'] == $original_cat) AND (!empty($pm_array['map_to_category']))){
1827
+ $cat_pieces = explode ("||",$original_cat);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1828
 
1829
+ if (count($cat_pieces) > 1){
1830
+ foreach ($cat_pieces as $k_piece => $v_piece){
1831
+ if($v_piece == $pm_array['criteria']){
 
 
 
 
 
 
 
 
 
1832
  $category_pieces = explode("-", $pm_array['map_to_category']);
1833
  $tmp_cat = $category_pieces[0];
1834
  $match = "true";
1835
+ } else {
1836
+ $product_data['categories'] = "";
1837
  }
1838
  }
1839
+ } else {
1840
+ if($original_cat == $pm_array['criteria']){
1841
  $category_pieces = explode("-", $pm_array['map_to_category']);
1842
  $tmp_cat = $category_pieces[0];
1843
  $match = "true";
 
 
1844
  }
1845
  }
1846
  }
1847
  }
1848
+
1849
  if($match == "true"){
1850
  $product_data['categories'] = $tmp_cat;
1851
+ } else {
1852
+ $product_data['categories'] = "";
1853
  }
1854
 
1855
  return $product_data;
2125
  return $product_data;
2126
  }
2127
 
2128
+ /**
2129
+ * Function to exclude products based on individual product exclusions
2130
+ */
2131
+ private function woosea_exclude_individual( $product_data ){
2132
+ $allowed = 1;
2133
+
2134
+ // Check if product was already excluded from the feed
2135
+ $product_excluded = ucfirst( get_post_meta( $product_data['id'], '_woosea_exclude_product', true ) );
2136
+
2137
+ if( $product_excluded == "Yes"){
2138
+ $allowed = 0;
2139
+ }
2140
+
2141
+ if ($allowed < 1){
2142
+ $product_data = array();
2143
+ $product_data = null;
2144
+ } else {
2145
+ return $product_data;
2146
+ }
2147
+ }
2148
+
2149
  /**
2150
  * Execute project filters (include / exclude)
2151
  */
2152
  private function woocommerce_sea_rules( $project_rules, $product_data ){
2153
+ $allowed = 1;
2154
 
2155
+ // Check if product was already excluded from the feed
2156
+ $product_excluded = ucfirst( get_post_meta( $product_data['id'], '_woosea_exclude_product', true ) );
2157
 
2158
+ if( $product_excluded == "Yes"){
2159
+ $allowed = 0;
2160
+ }
2161
 
2162
+ foreach ($project_rules as $pr_key => $pr_array){
2163
+ if(array_key_exists($pr_array['attribute'], $product_data)){
2164
 
2165
+ foreach ($product_data as $pd_key => $pd_value){
2166
+ // Check is there is a rule on specific attributes
2167
+ if(in_array($pd_key, $pr_array)){
2168
+
2169
+ if($pd_key == "price"){
2170
+ $pd_value = @number_format($pd_value,2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2171
  }
2172
+
2173
+ if (is_numeric($pd_value)){
2174
+ // Rules for numeric values
2175
+ switch ($pr_array['condition']) {
2176
+ case($pr_array['condition'] = "contains"):
2177
+ if ((preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "exclude")){
2178
+ $allowed = 0;
2179
+ } elseif ((!preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "include_only")){
2180
+ $allowed = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2181
  }
2182
+ break;
2183
+ case($pr_array['condition'] = "containsnot"):
2184
+ if ((!preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "exclude")){
2185
+ $allowed = 0;
2186
+ } elseif ((preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "include_only")){
2187
+ $allowed = 0;
2188
+ }
2189
+ break;
2190
+ case($pr_array['condition'] = "="):
2191
+ if (($pd_value == $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
2192
+ $allowed = 0;
2193
+ } elseif (($pd_value != $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
2194
+ $allowed = 0;
2195
+ }
2196
+ break;
2197
+ case($pr_array['condition'] = "!="):
2198
+ if (($pd_value == $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
2199
+ $allowed = 1;
2200
+ } elseif (($pd_value == $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
2201
+ $allowed = 0;
2202
+ }
2203
+ break;
2204
+ case($pr_array['condition'] = ">"):
2205
+ if (($pd_value > $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
2206
+ $allowed = 0;
2207
+ } elseif (($pd_value <= $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
2208
+ $allowed = 0;
2209
+ }
2210
+ break;
2211
+ case($pr_array['condition'] = ">="):
2212
+ if (($pd_value >= $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
2213
+ $allowed = 0;
2214
+ } elseif (($pd_value < $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
2215
+ $allowed = 0;
2216
+ }
2217
+ break;
2218
+ case($pr_array['condition'] = "<"):
2219
+ if (($pd_value < $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
2220
+ $allowed = 0;
2221
+ } elseif (($pd_value > $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
2222
+ $allowed = 0;
2223
+ }
2224
+ break;
2225
+ case($pr_array['condition'] = "=<"):
2226
+ if (($pd_value <= $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
2227
+ $allowed = 0;
2228
+ } elseif (($pd_value > $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
2229
+ $allowed = 0;
2230
+ }
2231
+ case($pr_array['condition'] = "empty"):
2232
+ if ((strlen($pd_value) < 1) && ($pr_array['than'] == "exclude")){
2233
+ $allowed = 0;
2234
+ } elseif ((strlen($pd_value > 0)) && ($pr_array['than'] == "include_only")){
2235
+ $allowed = 0;
2236
+ }
2237
+ break;
2238
+ default:
2239
+ break;
2240
  }
2241
+ } elseif (is_array($pd_value)){
2242
+
2243
+ // For now only shipping details are in an array
2244
+ foreach ($pd_value as $k => $v){
2245
+ foreach ($v as $kk => $vv){
2246
+ // Only shipping detail rule can be on price for now
2247
+ if($kk == "price"){
2248
+ switch ($pr_array['condition']) {
2249
+ case($pr_array['condition'] = "contains"):
2250
+ if ((preg_match('/'.$pr_array['criteria'].'/', $vv))){
2251
+ $allowed = 0;
2252
+ }
2253
+ break;
2254
+ case($pr_array['condition'] = "containsnot"):
2255
+ if ((!preg_match('/'.$pr_array['criteria'].'/', $vv))){
2256
+ $allowed = 0;
2257
+ }
2258
+ break;
2259
+ case($pr_array['condition'] = "="):
2260
+ if (($vv == $pr_array['criteria'])){
2261
+ $allowed = 0;
2262
+ }
2263
+ break;
2264
+ case($pr_array['condition'] = "!="):
2265
+ if (($vv != $pr_array['criteria'])){
2266
+ $allowed = 0;
2267
+ }
2268
+ break;
2269
+ case($pr_array['condition'] = ">"):
2270
+ if (($vv > $pr_array['criteria'])){
2271
+ $allowed = 0;
2272
+ }
2273
+ break;
2274
+ case($pr_array['condition'] = ">="):
2275
+ if (($vv >= $pr_array['criteria'])){
2276
+ $allowed = 0;
2277
+ }
2278
+ break;
2279
+ case($pr_array['condition'] = "<"):
2280
+ if (($vv < $pr_array['criteria'])){
2281
+ $allowed = 0;
2282
+ }
2283
+ break;
2284
+ case($pr_array['condition'] = "=<"):
2285
+ if (($vv <= $pr_array['criteria'])){
2286
+ $allowed = 0;
2287
+ }
2288
+ break;
2289
+ case($pr_array['condition'] = "empty"):
2290
+ if (strlen($vv) < 1){
2291
+ $allowed = 0;
2292
+ }
2293
+ break;
2294
+ default:
2295
+ break;
2296
+ }
2297
+ }
 
 
 
 
2298
  }
2299
+ }
2300
+ } else {
2301
+ // Rules for string values
2302
+
2303
+ // If case-sensitve is off than lowercase both the criteria and attribute value
2304
+ if (array_key_exists('cs', $pr_array)){
2305
+ if ($pr_array['cs'] != "on"){
2306
+ $pd_value = strtolower($pd_value);
2307
+ $pr_array['criteria'] = strtolower($pr_array['criteria']);
2308
  }
2309
+ }
2310
+
2311
+ switch ($pr_array['condition']) {
2312
+ case($pr_array['condition'] = "contains"):
2313
+ if ((preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "exclude")){
2314
+ $allowed = 0;
2315
+ } elseif ((!preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "include_only")){
2316
+ $allowed = 0;
2317
+ }
2318
+ break;
2319
+ case($pr_array['condition'] = "containsnot"):
2320
+ if ((!preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "exclude")){
2321
+ $allowed = 0;
2322
+ } elseif ((preg_match('/'.$pr_array['criteria'].'/', $pd_value)) && ($pr_array['than'] == "include_only")){
2323
+ $allowed = 0;
2324
+ }
2325
+ break;
2326
+ case($pr_array['condition'] = "="):
2327
+ if (($pr_array['criteria'] == "$pd_value") && ($pr_array['than'] == "exclude")){
2328
+ $allowed = 0;
2329
+ } elseif (($pr_array['criteria'] != "$pd_value") && ($pr_array['than'] == "include_only")){
2330
+ $allowed = 0;
2331
+ } elseif (($pr_array['criteria'] == "$pd_value") && ($pr_array['than'] == "include_only")){
2332
+ $allowed = 1;
2333
+ }
2334
+ break;
2335
+ case($pr_array['condition'] = "!="):
2336
+ if (($pr_array['criteria'] == "$pd_value") && ($pr_array['than'] == "exclude")){
2337
+ $allowed = 1;
2338
+ } elseif (($pr_array['criteria'] == "$pd_value") && ($pr_array['than'] == "include_only")){
2339
+ $allowed = 0;
2340
+ } elseif (($pr_array['criteria'] != "$pd_value") && ($pr_array['than'] == "exclude")){
2341
+ $allowed = 0;
2342
+ }
2343
+ break;
2344
+ case($pr_array['condition'] = ">"):
2345
+ // Use a lexical order on relational string operators
2346
+ if (($pd_value > $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
2347
+ $allowed = 0;
2348
+ } elseif (($pd_value < $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
2349
+ $allowed = 0;
2350
+ }
2351
+ break;
2352
+ case($pr_array['condition'] = ">="):
2353
+ // Use a lexical order on relational string operators
2354
+ if (($pd_value >= $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
2355
+ $allowed = 0;
2356
+ } elseif (($pd_value < $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
2357
+ $allowed = 0;
2358
+ }
2359
+ break;
2360
+ case($pr_array['condition'] = "<"):
2361
+ // Use a lexical order on relational string operators
2362
+ if (($pd_value < $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
2363
+ $allowed = 0;
2364
+ } elseif (($pd_value > $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
2365
+ $allowed = 0;
2366
+ }
2367
+ break;
2368
+ case($pr_array['condition'] = "=<"):
2369
+ // Use a lexical order on relational string operators
2370
+ if (($pd_value <= $pr_array['criteria']) && ($pr_array['than'] == "exclude")){
2371
+ $allowed = 0;
2372
+ } elseif (($pd_value > $pr_array['criteria']) && ($pr_array['than'] == "include_only")){
2373
+ $allowed = 0;
2374
+ }
2375
+ break;
2376
+ case($pr_array['condition'] = "empty"):
2377
+ if ((strlen($pd_value) < 1) && ($pr_array['than'] == "exclude")){
2378
+ $allowed = 0;
2379
+ } elseif ((strlen($pd_value > 0)) && ($pr_array['than'] == "include_only")){
2380
+ $allowed = 0;
2381
+ }
2382
+ break;
2383
+ default:
2384
+ break;
2385
+ }
2386
  }
2387
  }
2388
  }
2389
+ } else {
2390
+ // A empty rule has been set on an attribute that is not in a product anyhow. Still, remove this product from the feed
2391
+ if($pr_array['condition'] == "empty"){
2392
+ $allowed = 0;
2393
+ }
2394
  }
2395
  }
2396
+
2397
  if ($allowed < 1){
2398
  $product_data = array();
2399
  $product_data = null;
2400
+ } else {
2401
+ return $product_data;
2402
  }
 
2403
  }
2404
  }
classes/class-uninstall-cleanup.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Clean up your mess like your mom always told you to do :-)
4
+ * This class is called upon plugin uninstalling and cleans up cron hooks and wp_options
5
+ * When the plugin is removed completely the configured projects will be losed and deleted
6
+ */
7
+ class WooSEA_Uninstall_Cleanup {
8
+ public static function uninstall_cleanup() {
9
+ wp_clear_scheduled_hook( 'woosea_cron_hook' );
10
+ wp_clear_scheduled_hook( 'woosea_check_license' );
11
+ delete_option( 'channel_statics' );
12
+ delete_option( 'license_information' );
13
+ delete_option( 'cron_projects' );
14
+ }
15
+ }
classes/class-update-channel.php CHANGED
@@ -35,7 +35,8 @@ class WooSEA_Update_Project {
35
  public static function get_project_data($project_hash) {
36
  if(get_option( 'cron_projects' )){
37
  $cron_projects = get_option( 'cron_projects' );
38
-
 
39
  foreach ($cron_projects as $key=>$val){
40
  if(!empty($val)){
41
  if($val['project_hash'] == $project_hash){
@@ -47,9 +48,26 @@ class WooSEA_Update_Project {
47
  }
48
  }
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  public static function update_project($project_data){
51
  if(!array_key_exists('project_hash', $project_data)){
52
-
53
  $upload_dir = wp_upload_dir();
54
  $external_base = $upload_dir['baseurl'];
55
  $external_path = $external_base . "/woo-product-feed-pro/" . $project_data['fileformat'];
35
  public static function get_project_data($project_hash) {
36
  if(get_option( 'cron_projects' )){
37
  $cron_projects = get_option( 'cron_projects' );
38
+ $project_config = array();
39
+
40
  foreach ($cron_projects as $key=>$val){
41
  if(!empty($val)){
42
  if($val['project_hash'] == $project_hash){
48
  }
49
  }
50
 
51
+ /**
52
+ * Update individual project configuration
53
+ */
54
+ public static function update_project_data($project) {
55
+ if(get_option( 'cron_projects' )){
56
+ $cron_projects = get_option( 'cron_projects' );
57
+
58
+ foreach ($cron_projects as $key=>$val){
59
+ if(!empty($val)){
60
+ if($val['project_hash'] == $project['project_hash']){
61
+ $cron_projects[$key] = $project;
62
+ update_option('cron_projects', $cron_projects);
63
+ }
64
+ }
65
+ }
66
+ }
67
+ }
68
+
69
  public static function update_project($project_data){
70
  if(!array_key_exists('project_hash', $project_data)){
 
71
  $upload_dir = wp_upload_dir();
72
  $external_base = $upload_dir['baseurl'];
73
  $external_path = $external_base . "/woo-product-feed-pro/" . $project_data['fileformat'];
css/jquery-ui.css CHANGED
@@ -230,7 +230,7 @@ button.ui-button::-moz-focus-inner {
230
  position: relative;
231
  border: 0;
232
  padding: .5em 1em;
233
- background: none;
234
  overflow: auto;
235
  }
236
  .ui-dialog .ui-dialog-buttonpane {
230
  position: relative;
231
  border: 0;
232
  padding: .5em 1em;
233
+ background: white;
234
  overflow: auto;
235
  }
236
  .ui-dialog .ui-dialog-buttonpane {
js/woosea_autocomplete.js CHANGED
@@ -5431,7 +5431,8 @@ jQuery(document).ready(function($) {
5431
  ];
5432
 
5433
  jQuery(".js-autosuggest").click(function(){
5434
- var rowCount = $(this).closest("tr").prevAll("tr").length;
 
5435
 
5436
  jQuery( ".autocomplete_" + rowCount ).typeahead({
5437
  input: '.js-autosuggest',
@@ -5445,13 +5446,43 @@ jQuery(document).ready(function($) {
5445
  });
5446
  jQuery( ".autocomplete_" + rowCount ).focus();
5447
 
5448
- jQuery(this).keyup(function (){
5449
  var minimum = 5;
5450
  var len = jQuery(this).val().length;
 
 
 
5451
  if (len >= minimum){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5452
  jQuery(this).closest("input").removeClass("input-field-large");
5453
  jQuery(this).closest("input").addClass("input-field-large-active");
5454
  } else {
 
 
 
 
 
 
 
5455
  jQuery(this).closest("input").removeClass("input-field-large-active");
5456
  jQuery(this).closest("input").addClass("input-field-large");
5457
  }
@@ -5460,6 +5491,14 @@ jQuery(document).ready(function($) {
5460
  jQuery(this).click(function (){
5461
  var len = jQuery(this).val().length;
5462
  if (len < 1){
 
 
 
 
 
 
 
 
5463
  jQuery(this).closest("input").removeClass("input-field-large-active");
5464
  jQuery(this).closest("input").addClass("input-field-large");
5465
  }
5431
  ];
5432
 
5433
  jQuery(".js-autosuggest").click(function(){
5434
+ var className = $(this).attr("class").split(' ')[3];
5435
+ var rowCount = className.split("_")[1]
5436
 
5437
  jQuery( ".autocomplete_" + rowCount ).typeahead({
5438
  input: '.js-autosuggest',
5446
  });
5447
  jQuery( ".autocomplete_" + rowCount ).focus();
5448
 
5449
+ jQuery(this).blur(function (){
5450
  var minimum = 5;
5451
  var len = jQuery(this).val().length;
5452
+ var project_hash = $("#project_hash").val();
5453
+ var criteria = $("#" + rowCount).val();
5454
+
5455
  if (len >= minimum){
5456
+ jQuery(this).blur(function(){
5457
+ var map_to_category = jQuery(this).val();
5458
+
5459
+ jQuery.ajax({
5460
+ method: "POST",
5461
+ url: ajaxurl,
5462
+ data: { 'action': 'woosea_add_cat_mapping', 'rowCount': rowCount, 'map_to_category': map_to_category, 'className': className, 'project_hash': project_hash, 'criteria': criteria }
5463
+ })
5464
+
5465
+ .done(function( data ) {
5466
+ data = JSON.parse( data );
5467
+
5468
+ jQuery(data.className).removeClass("input-field-large");
5469
+ jQuery(data.className).addClass("input-field-large-active");
5470
+ })
5471
+
5472
+ .fail(function( data ) {
5473
+ console.log('Failed AJAX Call :( /// Return Data: ' + data);
5474
+ });
5475
+ });
5476
  jQuery(this).closest("input").removeClass("input-field-large");
5477
  jQuery(this).closest("input").addClass("input-field-large-active");
5478
  } else {
5479
+ var map_to_category = "";
5480
+
5481
+ jQuery.ajax({
5482
+ method: "POST",
5483
+ url: ajaxurl,
5484
+ data: { 'action': 'woosea_add_cat_mapping', 'rowCount': rowCount, 'map_to_category': map_to_category, 'className': className, 'project_hash': project_hash, 'criteria': criteria }
5485
+ })
5486
  jQuery(this).closest("input").removeClass("input-field-large-active");
5487
  jQuery(this).closest("input").addClass("input-field-large");
5488
  }
5491
  jQuery(this).click(function (){
5492
  var len = jQuery(this).val().length;
5493
  if (len < 1){
5494
+ var map_to_category = "";
5495
+
5496
+ jQuery.ajax({
5497
+ method: "POST",
5498
+ url: ajaxurl,
5499
+ data: { 'action': 'woosea_add_cat_mapping', 'rowCount': rowCount, 'map_to_category': map_to_category, 'className': className, 'project_hash': project_hash, 'criteria': criteria }
5500
+ })
5501
+
5502
  jQuery(this).closest("input").removeClass("input-field-large-active");
5503
  jQuery(this).closest("input").addClass("input-field-large");
5504
  }
js/woosea_channel.js CHANGED
@@ -29,7 +29,7 @@ jQuery(document).ready(function($) {
29
  } else {
30
  $("#fileformat")
31
  .empty()
32
- .append('<option value="csv">CSV</option><option value="txt">TXT</option><option value="xml">XML</option>')
33
  ;
34
  }
35
  });
@@ -109,7 +109,7 @@ jQuery(document).ready(function($) {
109
  } else {
110
  // Put delimiter dropdown back
111
  if($("#delimiter").length == 0){
112
- $('#file').after('<tr id="delimiter"><td><span>Delimiter:</span></td><td><select name="delimiter" class="select-field"><option value=",">, comma</option><option value="|">| pipe</option></select></td></tr>');
113
  }
114
  }
115
  });
29
  } else {
30
  $("#fileformat")
31
  .empty()
32
+ .append('<option value="xml">XML</option><option value="csv">CSV</option><option value="txt">TXT</option><option value="tsv">TSV</option>')
33
  ;
34
  }
35
  });
109
  } else {
110
  // Put delimiter dropdown back
111
  if($("#delimiter").length == 0){
112
+ $('#file').after('<tr id="delimiter"><td><span>Delimiter:</span></td><td><select name="delimiter" class="select-field"><option value=",">, comma</option><option value="|">| pipe</option><option value=";">;</option><option value="tab">tab</option></select></td></tr>');
113
  }
114
  }
115
  });
js/woosea_field_mapping.js CHANGED
@@ -1,11 +1,50 @@
1
  jQuery(document).ready(function($) {
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  // Add a mapping row to the table for field mappings
4
  jQuery(".add-field-mapping").click(function(){
5
  //var rowCount = $('#woosea-fieldmapping-table >tbody >tr').length-1;
6
  var channel_hash = $('#channel_hash').val();
7
  var prevRow = $("tr.rowCount:last input[type=hidden]").val();
8
- var rowCount = Number(prevRow) + Number(1);
 
 
 
 
 
9
 
10
  jQuery.ajax({
11
  method: "POST",
@@ -62,7 +101,7 @@ jQuery(document).ready(function($) {
62
 
63
  $("#own-input-field").each(function() {
64
  var input=$(this).val();
65
- var re = /^[a-zA-Z]*$/;
66
  var minLength = 2;
67
  var maxLength = 20;
68
 
1
  jQuery(document).ready(function($) {
2
 
3
+ // Dialog opener for information on mapping attributes
4
+ jQuery( "#dialog" ).dialog({
5
+ autoOpen: false,
6
+ show: {
7
+ effect: "blind",
8
+ duration: 1000
9
+ },
10
+ hide: {
11
+ effect: "explode",
12
+ duration: 1000
13
+ }
14
+ });
15
+
16
+ // Open jQuery dialog and get the right title and attribute helptext
17
+ jQuery( ".opener" ).on( "click", function() {
18
+ var id=$(this).attr('id');
19
+
20
+ jQuery.ajax({
21
+ method: "POST",
22
+ url: ajaxurl,
23
+ data: { 'action': 'woosea_fieldmapping_dialog_helptext', 'field': id }
24
+ })
25
+ .done(function( data ) {
26
+ data = JSON.parse( data );
27
+
28
+ jQuery("#dialogText").text(data.helptext); // set attribute helptext, get it via ajax
29
+ $( "#dialog" ).dialog( "open" );
30
+ $( "#dialog" ).dialog( "option", "title", id); // set title of dialog window
31
+ })
32
+ .fail(function( data ) {
33
+ console.log('Failed AJAX Call :( /// Return Data: ' + data);
34
+ });
35
+ });
36
+
37
  // Add a mapping row to the table for field mappings
38
  jQuery(".add-field-mapping").click(function(){
39
  //var rowCount = $('#woosea-fieldmapping-table >tbody >tr').length-1;
40
  var channel_hash = $('#channel_hash').val();
41
  var prevRow = $("tr.rowCount:last input[type=hidden]").val();
42
+ //var rowCount = Number(prevRow) + Number(1);
43
+ var addrow_value = $('#addrow').val();
44
+
45
+ var rowCount = Number(prevRow) + Number(addrow_value);
46
+ var newrow_value = Number(addrow_value) + Number(1);
47
+ $('#addrow').val(newrow_value);
48
 
49
  jQuery.ajax({
50
  method: "POST",
101
 
102
  $("#own-input-field").each(function() {
103
  var input=$(this).val();
104
+ var re = /^[a-zA-Z_]*$/;
105
  var minLength = 2;
106
  var maxLength = 20;
107
 
js/woosea_license.js CHANGED
@@ -1,12 +1,65 @@
1
  jQuery(document).ready(function($) {
2
 
3
- var temp = location.host.split('.').reverse();
4
- var root_domain = temp[1] + '.' + temp[0];
5
 
6
- jQuery.ajax({
7
- url: 'https://www.adtribes.io/conversion/conv.php?domain=' + root_domain + '&version=2.0.0&callback=',
8
- type: 'post',
9
- dataType: 'jsonp'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  });
11
 
12
  // On succes this call will return yes/no in jsonp for the domain name check. It will also return the license key. This key needs to correlate with the one user entered.
1
  jQuery(document).ready(function($) {
2
 
3
+ jQuery("#deactivate_license").click(function(){
 
4
 
5
+ $('.notice').replaceWith("<div class='notice notice-info is-dismissible'><p>Your license has been deactivated.</p></div>");
6
+ $('#license_email').val('');
7
+ $('#license_key').val('');
8
+
9
+ jQuery.ajax({
10
+ method: "POST",
11
+ url: ajaxurl,
12
+ data: { 'action': 'woosea_deactivate_license' }
13
+ })
14
+ .done(function( data ) {
15
+ data = JSON.parse( data );
16
+ })
17
+ .fail(function( data ) {
18
+ console.log('Failed AJAX Call :( /// Return Data: ' + data);
19
+ });
20
+ });
21
+
22
+ jQuery("#checklicense").click(function(){
23
+
24
+ var temp = location.host.split('.').reverse();
25
+ var root_domain = $(location).attr('hostname');
26
+ var license_email = $('#license-email').val();
27
+ var license_key = $('#license-key').val();
28
+
29
+ jQuery.ajax({
30
+ url: 'https://www.adtribes.io/check/license.php?key=' + license_key + '&email=' + license_email + '&domain=' + root_domain + '&version=3.0.0',
31
+ jsonp: 'callback',
32
+ dataType: 'jsonp',
33
+ type: 'GET',
34
+ success: function( licenseData ) {
35
+
36
+ var license_valid = licenseData.valid;
37
+ if (license_valid == "true"){
38
+ $('.notice').replaceWith("<div class='notice notice-success is-dismissible'><p>Thank you for registering your Elite product, your yearly license has been activated. Please do not hesitate to contact us whenever you have questions (support@adtribes.io).</p></div>");
39
+ } else {
40
+ $('.notice').replaceWith("<div class='notice notice-error is-dismissible'><p>Sorry, this does not seem to be a valid or active license key and email. Please feel free to contact us at support@adtribes.io whenever you have questions with regards to your license.</p></div>");
41
+ }
42
+
43
+ var license_created = licenseData.created;
44
+ var message = licenseData.message;
45
+ var message_type = licenseData.message_type;
46
+ var license_email = licenseData.license_email;
47
+ var license_key = licenseData.license_key;
48
+
49
+ jQuery.ajax({
50
+ method: "POST",
51
+ url: ajaxurl,
52
+ data: { 'action': 'woosea_register_license', 'message_type': message_type, 'license_email': license_email, 'license_key': license_key, 'license_valid': license_valid, 'license_created': license_created, 'message': message }
53
+ })
54
+ .done(function( data ) {
55
+ data = JSON.parse( data );
56
+ })
57
+ .fail(function( data ) {
58
+ console.log('Failed AJAX Call :( /// Return Data: ' + data);
59
+ });
60
+ console.log( licenseData );
61
+ }
62
+ })
63
  });
64
 
65
  // On succes this call will return yes/no in jsonp for the domain name check. It will also return the license key. This key needs to correlate with the one user entered.
js/woosea_manage.js CHANGED
@@ -2,6 +2,27 @@ jQuery(document).ready(function($) {
2
  var project_hash = null;
3
  var project_status = null;
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  $("td[colspan=8]").find("div").parents("tr").hide();
6
 
7
  $('.checkbox-field').change(function(index, obj){
@@ -26,6 +47,44 @@ jQuery(document).ready(function($) {
26
  });
27
  });
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  // Check if user would like to create an AdTribes.io Support user account
30
  $('#grant_access').on('change', function(){ // on change of state
31
  if(this.checked){
2
  var project_hash = null;
3
  var project_status = null;
4
 
5
+ $(".dismiss-review-notification").click(function(){
6
+ $(".review-notification").remove();
7
+
8
+ jQuery.ajax({
9
+ method: "POST",
10
+ url: ajaxurl,
11
+ data: { 'action': 'woosea_review_notification' }
12
+ })
13
+ });
14
+
15
+ $(".notice-dismiss").click(function(){
16
+ $(".license-notification").remove();
17
+
18
+ jQuery.ajax({
19
+ method: "POST",
20
+ url: ajaxurl,
21
+ data: { 'action': 'woosea_license_notification' }
22
+ })
23
+ });
24
+
25
+
26
  $("td[colspan=8]").find("div").parents("tr").hide();
27
 
28
  $('.checkbox-field').change(function(index, obj){
47
  });
48
  });
49
 
50
+ // Check if user would like to add attributes
51
+ $('#add_identifiers').on('change', function(){ // on change of state
52
+ if(this.checked){
53
+ // Checkbox is on
54
+ jQuery.ajax({
55
+ method: "POST",
56
+ url: ajaxurl,
57
+ data: { 'action': 'woosea_add_identifiers', 'status': "on" }
58
+ })
59
+ } else {
60
+ // Checkbox is off
61
+ jQuery.ajax({
62
+ method: "POST",
63
+ url: ajaxurl,
64
+ data: { 'action': 'woosea_add_identifiers', 'status': "off" }
65
+ })
66
+ }
67
+ })
68
+
69
+ // Check if user would like to fix the WooCommerce structured data bug
70
+ $('#fix_json_ld').on('change', function(){ // on change of state
71
+ if(this.checked){
72
+ // Checkbox is on
73
+ jQuery.ajax({
74
+ method: "POST",
75
+ url: ajaxurl,
76
+ data: { 'action': 'woosea_enable_structured_data', 'status': "on" }
77
+ })
78
+ } else {
79
+ // Checkbox is off
80
+ jQuery.ajax({
81
+ method: "POST",
82
+ url: ajaxurl,
83
+ data: { 'action': 'woosea_enable_structured_data', 'status': "off" }
84
+ })
85
+ }
86
+ })
87
+
88
  // Check if user would like to create an AdTribes.io Support user account
89
  $('#grant_access').on('change', function(){ // on change of state
90
  if(this.checked){
js/woosea_rules.js CHANGED
@@ -1,11 +1,11 @@
1
  jQuery(document).ready(function($) {
2
 
3
- // Add filters
4
  jQuery(".add-filter").click(function(){
5
  // Count amount of rows, used to create the form array field and values
6
- var rowCount = $('#woosea-ajax-table >tbody >tr').length-1;
7
- // var prevRow = $("tr.rowCount:last input[type=hidden]").val();
8
- //var rowCount = Number(prevRow) + Number(1);
9
 
10
  jQuery.ajax({
11
  method: "POST",
@@ -14,7 +14,7 @@ jQuery(document).ready(function($) {
14
  })
15
  .done(function( data ) {
16
  data = JSON.parse( data );
17
- $( '#woosea-ajax-table' ).append('<tr><td><input type="hidden" name="rules[' + data.rowCount + '][rowCount]" value="' + data.rowCount + '"><input type="checkbox" name="record" class="checkbox-field"></td><td><i>Filter:</i></td><td><select name="rules[' + data.rowCount + '][attribute]">' + data.dropdown + '</select></td><td><select name="rules[' + data.rowCount + '][condition]" class="select-field"><option value="contains">contains</option><option value="containsnot">does not contain</option><option value="=">is equal to</option><option value="!=">is not equal to</option><option value=">">is greater than</option><option value=">=">is greater or equal to</option><option value="<">is less than</option><option value="=<">is less or equal to</option><option value="empty">is empty</option></select></td><td><input type="text" name="rules[' + rowCount + '][criteria]" class="input-field-large"></td><td><input type="checkbox" name="rules[' + rowCount + '][cs]" class="checkbox-field" alt="Case sensitive"></td><td><select name="rules[' + rowCount + '][than]" class="select-field"><optgroup label="Action">Action:<option value="exclude"> Exclude</option><option value="include_only">Include only</option></optgroup></select></td><td>&nbsp;</td></tr>');
18
  })
19
  .fail(function( data ) {
20
  console.log('Failed AJAX Call :( /// Return Data: ' + data);
@@ -24,7 +24,8 @@ jQuery(document).ready(function($) {
24
  // Add rules
25
  jQuery(".add-rule").click(function(){
26
  // Count amount of rows, used to create the form array field and values
27
- var rowCount = $('#woosea-ajax-table >tbody >tr').length-1;
 
28
 
29
  jQuery.ajax({
30
  method: "POST",
1
  jQuery(document).ready(function($) {
2
 
3
+ // Add standard filters
4
  jQuery(".add-filter").click(function(){
5
  // Count amount of rows, used to create the form array field and values
6
+ // var rowCount = $('#woosea-ajax-table >tbody >tr').length-1;
7
+
8
+ var rowCount = Math.round(new Date().getTime() + (Math.random() * 100));
9
 
10
  jQuery.ajax({
11
  method: "POST",
14
  })
15
  .done(function( data ) {
16
  data = JSON.parse( data );
17
+ $( '#woosea-ajax-table' ).append('<tr><td><input type="hidden" name="rules[' + data.rowCount + '][rowCount]" value="' + data.rowCount + '"><input type="checkbox" name="record" class="checkbox-field"></td><td><i>Standard filter:</i></td><td><select name="rules[' + data.rowCount + '][attribute]">' + data.dropdown + '</select></td><td><select name="rules[' + data.rowCount + '][condition]" class="select-field"><option value="contains">contains</option><option value="containsnot">does not contain</option><option value="=">is equal to</option><option value="!=">is not equal to</option><option value=">">is greater than</option><option value=">=">is greater or equal to</option><option value="<">is less than</option><option value="=<">is less or equal to</option><option value="empty">is empty</option></select></td><td><input type="text" name="rules[' + rowCount + '][criteria]" class="input-field-large"></td><td><input type="checkbox" name="rules[' + rowCount + '][cs]" class="checkbox-field" alt="Case sensitive"></td><td><select name="rules[' + rowCount + '][than]" class="select-field"><optgroup label="Action">Action:<option value="exclude"> Exclude</option><option value="include_only">Include only</option></optgroup></select></td><td>&nbsp;</td></tr>');
18
  })
19
  .fail(function( data ) {
20
  console.log('Failed AJAX Call :( /// Return Data: ' + data);
24
  // Add rules
25
  jQuery(".add-rule").click(function(){
26
  // Count amount of rows, used to create the form array field and values
27
+ // var rowCount = $('#woosea-ajax-table >tbody >tr').length-1;
28
+ var rowCount = Math.round(new Date().getTime() + (Math.random() * 100));
29
 
30
  jQuery.ajax({
31
  method: "POST",
pages/admin/old-woosea-generate-feed-step-7.php CHANGED
@@ -3,7 +3,7 @@
3
  * Change default footer text, asking to review our plugin
4
  **/
5
  function my_footer_text($default) {
6
- return 'If you like our <strong>WooCommerce Product Feed PRO</strong> plugin please leave us a <a href="https://wordpress.org/support/plugin/woo-product-feed-pro/reviews?rate=5#new-post" target="_blank" class="ratingRequest">&#9733;&#9733;&#9733;&#9733;&#9733;</a> rating. Thanks in advance!';
7
  }
8
  add_filter('admin_footer_text', 'my_footer_text');
9
 
@@ -40,6 +40,12 @@ if($channel_data['taxonomy'] != "none"){
40
  $step = 1;
41
  }
42
 
 
 
 
 
 
 
43
  /**
44
  * Create channel attribute object
45
  **/
@@ -52,24 +58,37 @@ $attributes = $fields_obj->get_channel_attributes();
52
  * Add the Item Group ID attribute for product variations
53
  **/
54
  if(isset($_POST['product_variations'])){
55
- $attributes["Detailed product description"]["Item group ID"]["format"] = "required";
56
- $attributes["Detailed product description"]["Item group ID"]["woo_suggest"] = "item_group_id";
57
 
58
- if ((isset($project['fields'])) AND ($project['fields'] == "google_shopping")){
59
- $attributes["Detailed product description"]["Item group ID"]["feed_name"] = "g:item_group_id";
 
 
 
 
 
 
 
 
 
 
60
  }
61
  }
62
  ?>
 
 
 
 
 
63
 
64
  <div class="wrap">
65
- <div class="form-style-2">
66
- <div class="form-style-2-heading">Field mapping</div>
67
 
68
  <div class="<?php _e($notifications_box['message_type']); ?>">
69
  <p><?php _e($notifications_box['message'], 'sample-text-domain' ); ?></p>
70
  </div>
71
 
72
- <form action="" method="post">
73
  <table class="woo-product-feed-pro-table" id="woosea-fieldmapping-table" border="1">
74
  <thead>
75
  <tr>
@@ -87,23 +106,25 @@ if(isset($_POST['product_variations'])){
87
 
88
  <tbody class="woo-product-feed-pro-body">
89
  <?php
90
-
91
  if (!isset($count_mappings)){
92
  $c = 0;
 
93
  foreach($attributes as $row_key => $row_value){
94
  foreach($row_value as $row_k => $row_v){
95
  if ($row_v['format'] == "required"){
96
  ?>
97
- <tr>
98
  <td><input type="hidden" name="attributes[<?php print "$c";?>][rowCount]" value="<?php print "$c";?>"><input type="checkbox" name="record" class="checkbox-field"></td>
99
  <td>
100
  <select name="attributes[<?php print"$c"; ?>][attribute]" class="select-field">
101
  <?php
102
  foreach($attributes as $key => $value) {
103
  print "<optgroup label='$key'><strong>$key</strong>";
 
104
  foreach($value as $k => $v){
105
  if($v['feed_name'] == $row_v['feed_name']){
106
  if (array_key_exists('name',$v)){
 
107
  print "<option value='$v[feed_name]' selected>$k ($v[name])</option>";
108
  } else {
109
  print "<option value='$v[feed_name]' selected>$k</option>";
@@ -121,7 +142,13 @@ if(isset($_POST['product_variations'])){
121
  </select>
122
  </td>
123
  <td>
124
- <input type="text" name="attributes[<?php print "$c";?>][prefix]" class="input-field-medium">
 
 
 
 
 
 
125
  </td>
126
  <td>
127
  <select name="attributes[<?php print "$c";?>][mapfrom]" class="select-field">
@@ -151,51 +178,50 @@ if(isset($_POST['product_variations'])){
151
  }
152
  }
153
  } else {
154
- for ($i = 0; $i < $count_mappings; $i++){
155
- if(isset($project['attributes'][$i]['prefix'])){
156
- $prefix = $project['attributes'][$i]['prefix'];
157
  }
158
- if(isset($project['attributes'][$i]['suffix'])){
159
- $suffix = $project['attributes'][$i]['suffix'];
160
  }
161
  ?>
162
- <tr>
163
- <td><input type="hidden" name="attributes[<?php print "$i";?>][rowCount]" value="<?php print "$i";?>"><input type="checkbox" name="record" class="checkbox-field"></td>
164
  <td>
165
- <select name="attributes[<?php print"$i"; ?>][attribute]" class="select-field">
166
  <?php
167
- foreach($attributes as $key => $value) {
168
- print "<optgroup label='$key'><strong>$key</strong>";
169
- foreach($value as $k => $v){
170
- if ($project['attributes'][$i]['attribute'] == $v['feed_name']){
171
- print "<option value='$v[feed_name]' selected>$k ($v[name])</option>";
172
- } else {
173
- print "<option value='$v[feed_name]'>$k ($v[name])</option>";
174
- }
175
- }
176
- }
177
  ?>
178
  </select>
179
  </td>
180
  <td>
181
- <input type="text" name="attributes[<?php print "$i";?>][prefix]" class="input-field-medium" value="<?php print "$prefix";?>">
182
  </td>
183
  <td>
184
- <select name="attributes[<?php print "$i";?>][mapfrom]" class="select-field">
185
- <option></option>
186
  <?php
187
- foreach($attribute_dropdown as $drop_key => $drop_value){
188
- if($project['attributes'][$i]['mapfrom'] == $drop_key){
189
- print "<option value='$drop_key' selected>$drop_value</option>";
190
- } else {
191
- print "<option value='$drop_key'>$drop_value</option>";
 
 
 
 
 
 
 
 
192
  }
193
- }
 
 
194
  ?>
195
- </select>
196
  </td>
197
  <td>
198
- <input type="text" name="attributes[<?php print "$i";?>][suffix]" class="input-field-medium" value="<?php print "$suffix";?>">
199
  </td>
200
  </tr>
201
  <?php
@@ -205,21 +231,21 @@ if(isset($_POST['product_variations'])){
205
  </tbody>
206
 
207
  <tr>
208
- <td colspan="5">
209
  <input type="hidden" id="channel_hash" name="channel_hash" value="<?php print "$project[channel_hash]";?>">
210
  <?php
211
  if(isset($manage_project)){
212
  ?>
213
  <input type="hidden" name="project_hash" value="<?php print "$project[project_hash]";?>">
214
  <input type="hidden" name="step" value="100">
215
- <input type="button" class="delete-field-mapping" value="- Delete">&nbsp;<input type="button" class="add-field-mapping" value="+ Add field mapping">&nbsp;<input type="submit" value="Save" />
216
 
217
  <?php
218
  } else {
219
  ?>
220
  <input type="hidden" name="project_hash" value="<?php print "$project[project_hash]";?>">
221
  <input type="hidden" name="step" value="<?php print "$step";?>">
222
- <input type="button" class="delete-field-mapping" value="- Delete">&nbsp;<input type="button" class="add-field-mapping" value="+ Add field mapping">&nbsp;<input type="submit" value="Save" />
223
  <?php
224
  }
225
  ?>
3
  * Change default footer text, asking to review our plugin
4
  **/
5
  function my_footer_text($default) {
6
+ return 'If you like our <strong>WooCommerce Product Feed PRO</strong> plugin please leave us a <a href="https://wordpress.org/support/plugin/woo-product-feed-pro/reviews?rate=5#new-post" target="_blank" class="woo-product-feed-pro-ratingRequest">&#9733;&#9733;&#9733;&#9733;&#9733;</a> rating. Thanks in advance!';
7
  }
8
  add_filter('admin_footer_text', 'my_footer_text');
9
 
40
  $step = 1;
41
  }
42
 
43
+
44
+ /**
45
+ * Get main currency
46
+ **/
47
+ $currency = get_woocommerce_currency();
48
+
49
  /**
50
  * Create channel attribute object
51
  **/
58
  * Add the Item Group ID attribute for product variations
59
  **/
60
  if(isset($_POST['product_variations'])){
 
 
61
 
62
+ $channels_with_item_id = array('google_shopping','facebook_drm');
63
+
64
+ if (in_array($project['fields'],$channels_with_item_id)){
65
+
66
+ $attributes["Detailed product description"]["Item group ID"]["format"] = "required";
67
+ $attributes["Detailed product description"]["Item group ID"]["woo_suggest"] = "item_group_id";
68
+
69
+ if (in_array($project['fields'],$channels_with_item_id)){
70
+ $attributes["Detailed product description"]["Item group ID"]["feed_name"] = "g:item_group_id";
71
+ } else {
72
+ $attributes["Detailed product description"]["Item group ID"]["feed_name"] = "item_group_id";
73
+ }
74
  }
75
  }
76
  ?>
77
+ <div id="dialog" title="Basic dialog">
78
+ <p>
79
+ <div id="dialogText"></div>
80
+ </p>
81
+ </div>
82
 
83
  <div class="wrap">
84
+ <div class="woo-product-feed-pro-form-style-2">
85
+ <div class="woo-product-feed-pro-form-style-2-heading">Field mapping</div>
86
 
87
  <div class="<?php _e($notifications_box['message_type']); ?>">
88
  <p><?php _e($notifications_box['message'], 'sample-text-domain' ); ?></p>
89
  </div>
90
 
91
+ <form action="" id="fieldmapping" method="post">
92
  <table class="woo-product-feed-pro-table" id="woosea-fieldmapping-table" border="1">
93
  <thead>
94
  <tr>
106
 
107
  <tbody class="woo-product-feed-pro-body">
108
  <?php
 
109
  if (!isset($count_mappings)){
110
  $c = 0;
111
+
112
  foreach($attributes as $row_key => $row_value){
113
  foreach($row_value as $row_k => $row_v){
114
  if ($row_v['format'] == "required"){
115
  ?>
116
+ <tr class="rowCount">
117
  <td><input type="hidden" name="attributes[<?php print "$c";?>][rowCount]" value="<?php print "$c";?>"><input type="checkbox" name="record" class="checkbox-field"></td>
118
  <td>
119
  <select name="attributes[<?php print"$c"; ?>][attribute]" class="select-field">
120
  <?php
121
  foreach($attributes as $key => $value) {
122
  print "<optgroup label='$key'><strong>$key</strong>";
123
+
124
  foreach($value as $k => $v){
125
  if($v['feed_name'] == $row_v['feed_name']){
126
  if (array_key_exists('name',$v)){
127
+ $dialog_value = $v['feed_name'];
128
  print "<option value='$v[feed_name]' selected>$k ($v[name])</option>";
129
  } else {
130
  print "<option value='$v[feed_name]' selected>$k</option>";
142
  </select>
143
  </td>
144
  <td>
145
+ <?php
146
+ if($row_v['feed_name'] == "g:price"){
147
+ print "<input type='text' name='attributes[$c][prefix]' value='$currency' class='input-field-medium'>";
148
+ } else {
149
+ print "<input type='text' name='attributes[$c][prefix]' class='input-field-medium'>";
150
+ }
151
+ ?>
152
  </td>
153
  <td>
154
  <select name="attributes[<?php print "$c";?>][mapfrom]" class="select-field">
178
  }
179
  }
180
  } else {
181
+ foreach ($project['attributes'] as $attribute_key => $attribute_array){
182
+ if(isset($project['attributes'][$attribute_key]['prefix'])){
183
+ $prefix = $project['attributes'][$attribute_key]['prefix'];
184
  }
185
+ if(isset($project['attributes'][$attribute_key]['suffix'])){
186
+ $suffix = $project['attributes'][$attribute_key]['suffix'];
187
  }
188
  ?>
189
+ <tr class="rowCount">
190
+ <td><input type="hidden" name="attributes[<?php print "$attribute_key";?>][rowCount]" value="<?php print "$attribute_key";?>"><input type="checkbox" name="record" class="checkbox-field"></td>
191
  <td>
192
+ <select name="attributes[<?php print"$attribute_key"; ?>][attribute]" class="select-field">
193
  <?php
194
+ print "<option value=\"$attribute_array[attribute]\">$attribute_array[attribute]</option>";
 
 
 
 
 
 
 
 
 
195
  ?>
196
  </select>
197
  </td>
198
  <td>
199
+ <input type="text" name="attributes[<?php print "$attribute_key";?>][prefix]" class="input-field-medium" value="<?php print "$prefix";?>">
200
  </td>
201
  <td>
202
+
 
203
  <?php
204
+ if(array_key_exists('static_value', $attribute_array)){
205
+ print "<input type=\"text\" name=\"attributes[$attribute_key][mapfrom]\" class=\"input-field-midsmall\" value=\"$attribute_array[mapfrom]\"><input type=\"hidden\" name=\"attributes[$attribute_key][static_value]\" value=\"true\">";
206
+ } else {
207
+ ?>
208
+ <select name="attributes[<?php print "$attribute_key";?>][mapfrom]" class="select-field">
209
+ <option></option>
210
+ <?php
211
+ foreach($attribute_dropdown as $drop_key => $drop_value){
212
+ if($project['attributes'][$attribute_key]['mapfrom'] == $drop_key){
213
+ print "<option value='$drop_key' selected>$drop_value</option>";
214
+ } else {
215
+ print "<option value='$drop_key'>$drop_value</option>";
216
+ }
217
  }
218
+ ?>
219
+ </select>
220
+ <?php }
221
  ?>
 
222
  </td>
223
  <td>
224
+ <input type="text" name="attributes[<?php print "$attribute_key";?>][suffix]" class="input-field-medium" value="<?php print "$suffix";?>">
225
  </td>
226
  </tr>
227
  <?php
231
  </tbody>
232
 
233
  <tr>
234
+ <td colspan="6">
235
  <input type="hidden" id="channel_hash" name="channel_hash" value="<?php print "$project[channel_hash]";?>">
236
  <?php
237
  if(isset($manage_project)){
238
  ?>
239
  <input type="hidden" name="project_hash" value="<?php print "$project[project_hash]";?>">
240
  <input type="hidden" name="step" value="100">
241
+ <input type="button" class="delete-field-mapping" value="- Delete">&nbsp;<input type="button" class="add-field-mapping" value="+ Add field mapping">&nbsp;<input type="button" class="add-own-mapping" value="+ Add custom field">&nbsp;<input type="submit" id="savebutton" value="Save" />
242
 
243
  <?php
244
  } else {
245
  ?>
246
  <input type="hidden" name="project_hash" value="<?php print "$project[project_hash]";?>">
247
  <input type="hidden" name="step" value="<?php print "$step";?>">
248
+ <input type="button" class="delete-field-mapping" value="- Delete">&nbsp;<input type="button" class="add-field-mapping" value="+ Add field mapping">&nbsp;<input type="button" class="add-own-mapping" value="+ Add custom field">&nbsp;<input type="submit" id="savebutton" value="Save" />
249
  <?php
250
  }
251
  ?>
pages/admin/woosea-generate-feed-step-0.php CHANGED
@@ -246,7 +246,7 @@ if (array_key_exists('project_hash', $_GET)){
246
  <td>
247
  <select name="fileformat" id="fileformat" class="select-field">
248
  <?php
249
- $format_arr = array("csv","txt","xml");
250
  foreach ($format_arr as $format){
251
  $format_upper = strtoupper($format);
252
  if ((isset($project)) AND ($format == $project['fileformat'])){
@@ -264,7 +264,7 @@ if (array_key_exists('project_hash', $_GET)){
264
  <td>
265
  <select name="delimiter" class="select-field">
266
  <?php
267
- $delimiter_arr = array(",","|",";");
268
  foreach ($delimiter_arr as $delimiter){
269
  if((isset($project)) AND (array_key_exists('delimiter', $project)) AND ($delimiter == $project['delimiter'])){
270
  print "<option value=\"$delimiter\" selected>$delimiter</option>";
@@ -281,7 +281,7 @@ if (array_key_exists('project_hash', $_GET)){
281
  <td>
282
  <select name="cron" class="select-field">
283
  <?php
284
- $refresh_arr = array("daily","twicedaily","hourly");
285
  foreach ($refresh_arr as $refresh){
286
  $refresh_upper = ucfirst($refresh);
287
  if ((isset($project)) AND ($refresh == $project['cron'])){
@@ -315,34 +315,45 @@ if (array_key_exists('project_hash', $_GET)){
315
  </table>
316
  </div>
317
  <div class="woo-product-feed-pro-table-right">
318
- <!--
 
319
  <table class="woo-product-feed-pro-table">
320
  <tr>
321
- <td><strong>Tutorials</strong></td>
322
  </tr>
323
  <tr>
324
- <td><br/><br/><br/><br/></td>
 
 
 
 
 
 
 
 
 
325
  </tr>
326
  </table><br/>
327
- -->
328
 
329
  <table class="woo-product-feed-pro-table">
330
  <tr>
331
- <td><strong>We’ve got you covered!</strong></td>
332
  </tr>
333
  <tr>
334
  <td>
335
- Need assistance? Check out our:
336
  <ul>
337
- <li><strong><a href="https://adtribes.io/support/" target="_blank">F.A.Q.</a></strong></li>
338
- <li><strong><a href="https://www.youtube.com/channel/UCXp1NsK-G_w0XzkfHW-NZCw" target="_blank">YouTube tutorials</a></strong></li>
 
 
339
  </ul>
340
- Or just reach out to us at <a href="mailto:support@adtribes.io">support@adtribes.io</a> and we'll make sure your product feeds will be up-and-running within no-time.
341
- </td>
 
 
342
  </tr>
343
- </table>
344
-
345
-
346
 
347
  </div>
348
  </div>
246
  <td>
247
  <select name="fileformat" id="fileformat" class="select-field">
248
  <?php
249
+ $format_arr = array("xml","csv","txt","tsv");
250
  foreach ($format_arr as $format){
251
  $format_upper = strtoupper($format);
252
  if ((isset($project)) AND ($format == $project['fileformat'])){
264
  <td>
265
  <select name="delimiter" class="select-field">
266
  <?php
267
+ $delimiter_arr = array(",","|",";","tab");
268
  foreach ($delimiter_arr as $delimiter){
269
  if((isset($project)) AND (array_key_exists('delimiter', $project)) AND ($delimiter == $project['delimiter'])){
270
  print "<option value=\"$delimiter\" selected>$delimiter</option>";
281
  <td>
282
  <select name="cron" class="select-field">
283
  <?php
284
+ $refresh_arr = array("daily","twicedaily","hourly","no refresh");
285
  foreach ($refresh_arr as $refresh){
286
  $refresh_upper = ucfirst($refresh);
287
  if ((isset($project)) AND ($refresh == $project['cron'])){
315
  </table>
316
  </div>
317
  <div class="woo-product-feed-pro-table-right">
318
+
319
+
320
  <table class="woo-product-feed-pro-table">
321
  <tr>
322
+ <td><strong>We’ve got you covered!</strong></td>
323
  </tr>
324
  <tr>
325
+ <td>
326
+ Need assistance? Check out our:
327
+ <ul>
328
+ <li><strong><a href="https://adtribes.io/support/" target="_blank">Frequently Asked Questions</a></strong></li>
329
+ <li><strong><a href="https://www.youtube.com/channel/UCXp1NsK-G_w0XzkfHW-NZCw" target="_blank">YouTube tutorials</a></strong></li>
330
+ <li><strong><a href="https://adtribes.io/blog/" target="_blank">Blog</a></strong></li>
331
+ <li><strong><a href="https://adtribes.io/pro-vs-elite/?utm_source=$domain&utm_medium=plugin&utm_campaign=upgrade-elite" target="_blank">Upgrade to Elite</a></strong></li>
332
+ </ul>
333
+ Or just reach out to us at <strong><a href="https://wordpress.org/support/plugin/woo-product-feed-pro/" target="_blank">the support forum</a></strong> and we'll make sure your product feeds will be up-and-running within no-time.
334
+ </td>
335
  </tr>
336
  </table><br/>
 
337
 
338
  <table class="woo-product-feed-pro-table">
339
  <tr>
340
+ <td><strong>Why upgrade to Elite?</strong></td>
341
  </tr>
342
  <tr>
343
  <td>
344
+ Enjoy all priviliges of our Elite features and priority support and upgrade to the Elite version of our plugin now!
345
  <ul>
346
+ <li><strong>1.</strong> More products approved by Google</li>
347
+ <li><strong>2.</strong> Add GTIN, brand and more fields to your store</li>
348
+ <li><strong>3.</strong> Exclude individual products from your feeds</li>
349
+ <li><strong>4.</strong> Priority support</li>
350
  </ul>
351
+ <strong>
352
+ <a href="https://adtribes.io/pro-vs-elite/?utm_source=$domain&utm_medium=plugin&utm_campaign=upgrade-elite" target="_blank">Upgrade to Elite here!</a>
353
+ </strong>
354
+ </td>
355
  </tr>
356
+ </table><br/>
 
 
357
 
358
  </div>
359
  </div>
pages/admin/woosea-generate-feed-step-1.php CHANGED
@@ -24,6 +24,48 @@ if (array_key_exists('project_hash', $_GET)){
24
  $project = WooSEA_Update_Project::update_project($_POST);
25
  $channel_data = WooSEA_Update_Project::get_channel_data(sanitize_text_field($_POST['channel_hash']));
26
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  ?>
28
 
29
  <div class="wrap">
@@ -34,8 +76,6 @@ if (array_key_exists('project_hash', $_GET)){
34
  <p><?php _e($notifications_box['message'], 'sample-text-domain' ); ?></p>
35
  </div>
36
 
37
- <form action="" method="post">
38
-
39
  <div class="woo-product-feed-pro-table-wrapper">
40
  <div class="woo-product-feed-pro-table-left">
41
 
@@ -49,14 +89,6 @@ if (array_key_exists('project_hash', $_GET)){
49
 
50
  <tbody class="woo-product-feed-pro-body">
51
  <?php
52
- $x = 0;
53
- $cat_args = array(
54
- 'hide_empty' => false,
55
- 'no_found_rows' => true,
56
- 'update_term_meta_cache' => false
57
- );
58
- $all_categories = get_terms( 'product_cat', $cat_args );
59
-
60
  // Get already mapped categories
61
  $prev_mapped = array();
62
  if(isset($project['mappings'])){
@@ -66,41 +98,14 @@ if (array_key_exists('project_hash', $_GET)){
66
  $prev_mapped[$map_value['criteria']] = $map_value['map_to_category'];
67
  }
68
  }
69
- }
70
-
71
- foreach($all_categories as $sub_category) {
72
- $woo_category = $sub_category->name;
73
- $woo_category_id = $sub_category->term_id;
74
- $mapped_category = "";
75
- $mapped_active_class = "input-field-large";
76
- $nr_prods = $sub_category->count;
77
-
78
- $woo_category = preg_replace('/&amp;/','&',$woo_category);
79
-
80
- if (array_key_exists($woo_category, $prev_mapped)){
81
- $mapped_category = $prev_mapped[$woo_category];
82
- $mapped_active_class = "input-field-large-active";
83
- }
84
-
85
- ?>
86
- <tr>
87
- <td>
88
- <input type="hidden" name="mappings[<?php print "$x";?>][attribute]" value="categories">
89
- <input type="hidden" name="mappings[<?php print "$x";?>][condition]" value="=">
90
- <input type="hidden" name="mappings[<?php print "$x";?>][rowCount]" value="<?php print "$x";?>">
91
- <input type="hidden" name="mappings[<?php print "$x";?>][categoryId]" value="<?php print "$woo_category_id";?>">
92
- <input type="hidden" name="mappings[<?php print "$x";?>][criteria]" class="input-field-large" value="<?php print "$woo_category";?>"> <?php print "$woo_category <i>($nr_prods)</i>";?>
93
- </td>
94
- <td>
95
- <input type="search" name="mappings[<?php print "$x";?>][map_to_category]" class="<?php print "$mapped_active_class";?> js-typeahead js-autosuggest autocomplete_<?php print "$x";?>" value="<?php print "$mapped_category";?>">
96
- </td>
97
- </tr>
98
- <?php
99
- $x++;
100
  }
 
 
101
  ?>
102
  </tbody>
103
-
 
 
104
  <tr>
105
  <td colspan="2">
106
  <input type="hidden" id="channel_hash" name="channel_hash" value="<?php print "$project[channel_hash]";?>">
@@ -108,13 +113,13 @@ if (array_key_exists('project_hash', $_GET)){
108
  if(isset($manage_project)){
109
  ?>
110
  <input type="hidden" name="project_update" id="project_update" value="yes" />
111
- <input type="hidden" name="project_hash" value="<?php print "$project[project_hash]";?>">
112
  <input type="hidden" name="step" value="100">
113
  <input type="submit" value="Save mappings" />
114
  <?php
115
  } else {
116
  ?>
117
- <input type="hidden" name="project_hash" value="<?php print "$project[project_hash]";?>">
118
  <input type="hidden" name="step" value="4">
119
  <input type="submit" value="Save mappings" />
120
  <?php
@@ -122,20 +127,13 @@ if (array_key_exists('project_hash', $_GET)){
122
  ?>
123
  </td>
124
  </tr>
 
 
 
125
  </table>
126
  </div>
127
 
128
- <div class="woo-product-feed-pro-table-right">
129
- <!--
130
- <table class="woo-product-feed-pro-table">
131
- <tr>
132
- <td><strong>Tutorials</strong></td>
133
- </tr>
134
- <tr>
135
- <td><br/><br/><br/><br/></td>
136
- </tr>
137
- </table><br/>
138
- -->
139
 
140
  <table class="woo-product-feed-pro-table">
141
  <tr>
@@ -151,12 +149,26 @@ if (array_key_exists('project_hash', $_GET)){
151
  Or just reach out to us at <a href="mailto:support@adtribes.io">support@adtribes.io</a> and we'll make sure your product feeds will be up-and-running within no-time.
152
  </td>
153
  </tr>
154
- </table>
155
-
156
-
157
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  </div>
159
- </div>
160
- </form>
161
  </div>
162
  </div>
24
  $project = WooSEA_Update_Project::update_project($_POST);
25
  $channel_data = WooSEA_Update_Project::get_channel_data(sanitize_text_field($_POST['channel_hash']));
26
  }
27
+
28
+ function woosea_hierarchical_term_tree($category, $prev_mapped){
29
+ $r = '';
30
+
31
+ $args = array(
32
+ 'parent' => $category,
33
+ 'hide_empty' => false,
34
+ 'no_found_rows' => true,
35
+ );
36
+
37
+ $next = get_terms('product_cat', $args);
38
+
39
+ if ($next) {
40
+ foreach ($next as $sub_category) {
41
+ $x = $sub_category->term_id;
42
+ $woo_category = $sub_category->name;
43
+ $woo_category_id = $sub_category->term_id;
44
+ $mapped_category = "";
45
+ $mapped_active_class = "input-field-large";
46
+ $woo_category = preg_replace('/&amp;/','&',$woo_category);
47
+
48
+ if (array_key_exists($woo_category, $prev_mapped)){
49
+ $mapped_category = $prev_mapped[$woo_category];
50
+ $mapped_active_class = "input-field-large-active";
51
+ }
52
+
53
+ if($sub_category->parent == 0){
54
+ $r .= "<tr>";
55
+ $r .= "<td><input type=\"hidden\" name=\"mappings[$x][rowCount]\" value=\"$x\"><input type=\"hidden\" name=\"mappings[$x][categoryId]\" value=\"$woo_category_id\"><input type=\"hidden\" name=\"mappings[$x][criteria]\" class=\"input-field-large\" id=\"$woo_category_id\" value=\"$woo_category\">$woo_category ($sub_category->count)</td>";
56
+ $r .= "<td><input type=\"search\" name=\"mappings[$x][map_to_category]\" class=\"$mapped_active_class js-typeahead js-autosuggest autocomplete_$x\" value=\"$mapped_category\"></td>";
57
+ $r .= "</tr>";
58
+ } else {
59
+ $r .= "<tr>";
60
+ $r .= "<td><input type=\"hidden\" name=\"mappings[$x][rowCount]\" value=\"$x\"><input type=\"hidden\" name=\"mappings[$x][categoryId]\" value=\"$woo_category_id\"><input type=\"hidden\" name=\"mappings[$x][criteria]\" class=\"input-field-large\" id=\"$woo_category_id\" value=\"$woo_category\">-- $woo_category ($sub_category->count)</td>";
61
+ $r .= "<td><input type=\"search\" name=\"mappings[$x][map_to_category]\" class=\"$mapped_active_class js-typeahead js-autosuggest autocomplete_$x\" value=\"$mapped_category\"></td>";
62
+ $r .= "</tr>";
63
+ }
64
+ $r .= $sub_category->term_id !== 0 ? woosea_hierarchical_term_tree($sub_category->term_id, $prev_mapped) : null;
65
+ }
66
+ }
67
+ return $r;
68
+ }
69
  ?>
70
 
71
  <div class="wrap">
76
  <p><?php _e($notifications_box['message'], 'sample-text-domain' ); ?></p>
77
  </div>
78
 
 
 
79
  <div class="woo-product-feed-pro-table-wrapper">
80
  <div class="woo-product-feed-pro-table-left">
81
 
89
 
90
  <tbody class="woo-product-feed-pro-body">
91
  <?php
 
 
 
 
 
 
 
 
92
  // Get already mapped categories
93
  $prev_mapped = array();
94
  if(isset($project['mappings'])){
98
  $prev_mapped[$map_value['criteria']] = $map_value['map_to_category'];
99
  }
100
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  }
102
+ // Display mapping form
103
+ echo woosea_hierarchical_term_tree(0,$prev_mapped);
104
  ?>
105
  </tbody>
106
+
107
+ <form action="" method="post">
108
+
109
  <tr>
110
  <td colspan="2">
111
  <input type="hidden" id="channel_hash" name="channel_hash" value="<?php print "$project[channel_hash]";?>">
113
  if(isset($manage_project)){
114
  ?>
115
  <input type="hidden" name="project_update" id="project_update" value="yes" />
116
+ <input type="hidden" id="project_hash" name="project_hash" value="<?php print "$project[project_hash]";?>">
117
  <input type="hidden" name="step" value="100">
118
  <input type="submit" value="Save mappings" />
119
  <?php
120
  } else {
121
  ?>
122
+ <input type="hidden" id="project_hash" name="project_hash" value="<?php print "$project[project_hash]";?>">
123
  <input type="hidden" name="step" value="4">
124
  <input type="submit" value="Save mappings" />
125
  <?php
127
  ?>
128
  </td>
129
  </tr>
130
+
131
+ </form>
132
+
133
  </table>
134
  </div>
135
 
136
+ <div class="woo-product-feed-pro-table-right">
 
 
 
 
 
 
 
 
 
 
137
 
138
  <table class="woo-product-feed-pro-table">
139
  <tr>
149
  Or just reach out to us at <a href="mailto:support@adtribes.io">support@adtribes.io</a> and we'll make sure your product feeds will be up-and-running within no-time.
150
  </td>
151
  </tr>
152
+ </table><br/>
 
 
153
 
154
+ <table class="woo-product-feed-pro-table">
155
+ <tr>
156
+ <td><strong>Upgrade to Elite</strong></td>
157
+ </tr>
158
+ <tr>
159
+ <td>
160
+ Enjoy all priviliges of our Elite features and priority support and upgrade to the Elite version of our plugin now!
161
+ <ul>
162
+ <li><strong>1.</strong> More products approved by Google </li>
163
+ <li><strong>2.</strong> Add GTIN, brand and more fields to your store</li>
164
+ <li><strong>3.</strong> Exclude individual products from your product feeds</li>
165
+ <li><strong>4.</strong> Priority support</li>
166
+ </ul>
167
+ <a href="https://adtribes.io/pro-vs-elite/?utm_source=$domain&utm_medium=plugin&utm_campaign=upgrade-elite" target="_blank">Upgrade to Elite here!</a>
168
+ </td>
169
+ </tr>
170
+ </table><br/>
171
  </div>
172
+ </div>
 
173
  </div>
174
  </div>
pages/admin/woosea-generate-feed-step-4.php CHANGED
@@ -326,13 +326,13 @@ if (array_key_exists('project_hash', $_GET)){
326
  ?>
327
  <input type="hidden" name="project_hash" value="<?php print "$project[project_hash]";?>">
328
  <input type="hidden" name="step" value="100">
329
- <input type="button" class="delete-row" value="- Delete">&nbsp;<input type="button" class="add-filter" value="+ Add filter">&nbsp;<input type="button" class="add-rule" value="+ Add rule">&nbsp;<input type="submit" value="Save" />
330
  <?php
331
  } else {
332
  ?>
333
  <input type="hidden" name="project_hash" value="<?php print "$project[project_hash]";?>">
334
  <input type="hidden" name="step" value="5">
335
- <input type="button" class="delete-row" value="- Delete">&nbsp;<input type="button" class="add-filter" value="+ Add filter">&nbsp;<input type="button" class="add-rule" value="+ Add rule">&nbsp;<input type="submit" value="Save / Continue" />
336
  <?php
337
  }
338
  ?>
326
  ?>
327
  <input type="hidden" name="project_hash" value="<?php print "$project[project_hash]";?>">
328
  <input type="hidden" name="step" value="100">
329
+ <input type="button" class="delete-row" value="- Delete">&nbsp;<input type="button" class="add-filter" value="+ Add standard filter">&nbsp;<input type="button" class="add-rule" value="+ Add rule">&nbsp;<input type="submit" value="Save" />
330
  <?php
331
  } else {
332
  ?>
333
  <input type="hidden" name="project_hash" value="<?php print "$project[project_hash]";?>">
334
  <input type="hidden" name="step" value="5">
335
+ <input type="button" class="delete-row" value="- Delete">&nbsp;<input type="button" class="add-filter" value="+ Add standard filter">&nbsp;<input type="button" class="add-rule" value="+ Add rule">&nbsp;<input type="submit" value="Save / Continue" />
336
  <?php
337
  }
338
  ?>
pages/admin/woosea-generate-feed-step-7.php CHANGED
@@ -40,6 +40,12 @@ if($channel_data['taxonomy'] != "none"){
40
  $step = 1;
41
  }
42
 
 
 
 
 
 
 
43
  /**
44
  * Create channel attribute object
45
  **/
@@ -52,16 +58,27 @@ $attributes = $fields_obj->get_channel_attributes();
52
  * Add the Item Group ID attribute for product variations
53
  **/
54
  if(isset($_POST['product_variations'])){
55
- $attributes["Detailed product description"]["Item group ID"]["format"] = "required";
56
- $attributes["Detailed product description"]["Item group ID"]["woo_suggest"] = "item_group_id";
57
 
58
- if ((isset($project['fields'])) AND ($project['fields'] == "google_shopping")){
59
- $attributes["Detailed product description"]["Item group ID"]["feed_name"] = "g:item_group_id";
60
- } else {
61
- $attributes["Detailed product description"]["Item group ID"]["feed_name"] = "item_group_id";
 
 
 
 
 
 
 
 
62
  }
63
  }
64
  ?>
 
 
 
 
 
65
 
66
  <div class="wrap">
67
  <div class="woo-product-feed-pro-form-style-2">
@@ -107,6 +124,7 @@ if(isset($_POST['product_variations'])){
107
  foreach($value as $k => $v){
108
  if($v['feed_name'] == $row_v['feed_name']){
109
  if (array_key_exists('name',$v)){
 
110
  print "<option value='$v[feed_name]' selected>$k ($v[name])</option>";
111
  } else {
112
  print "<option value='$v[feed_name]' selected>$k</option>";
@@ -124,7 +142,13 @@ if(isset($_POST['product_variations'])){
124
  </select>
125
  </td>
126
  <td>
127
- <input type="text" name="attributes[<?php print "$c";?>][prefix]" class="input-field-medium">
 
 
 
 
 
 
128
  </td>
129
  <td>
130
  <select name="attributes[<?php print "$c";?>][mapfrom]" class="select-field">
@@ -214,6 +238,7 @@ if(isset($_POST['product_variations'])){
214
  ?>
215
  <input type="hidden" name="project_hash" value="<?php print "$project[project_hash]";?>">
216
  <input type="hidden" name="step" value="100">
 
217
  <input type="button" class="delete-field-mapping" value="- Delete">&nbsp;<input type="button" class="add-field-mapping" value="+ Add field mapping">&nbsp;<input type="button" class="add-own-mapping" value="+ Add custom field">&nbsp;<input type="submit" id="savebutton" value="Save" />
218
 
219
  <?php
@@ -221,6 +246,7 @@ if(isset($_POST['product_variations'])){
221
  ?>
222
  <input type="hidden" name="project_hash" value="<?php print "$project[project_hash]";?>">
223
  <input type="hidden" name="step" value="<?php print "$step";?>">
 
224
  <input type="button" class="delete-field-mapping" value="- Delete">&nbsp;<input type="button" class="add-field-mapping" value="+ Add field mapping">&nbsp;<input type="button" class="add-own-mapping" value="+ Add custom field">&nbsp;<input type="submit" id="savebutton" value="Save" />
225
  <?php
226
  }
40
  $step = 1;
41
  }
42
 
43
+
44
+ /**
45
+ * Get main currency
46
+ **/
47
+ $currency = get_woocommerce_currency();
48
+
49
  /**
50
  * Create channel attribute object
51
  **/
58
  * Add the Item Group ID attribute for product variations
59
  **/
60
  if(isset($_POST['product_variations'])){
 
 
61
 
62
+ $channels_with_item_id = array('google_shopping','facebook_drm');
63
+
64
+ if (in_array($project['fields'],$channels_with_item_id)){
65
+
66
+ $attributes["Detailed product description"]["Item group ID"]["format"] = "required";
67
+ $attributes["Detailed product description"]["Item group ID"]["woo_suggest"] = "item_group_id";
68
+
69
+ if (in_array($project['fields'],$channels_with_item_id)){
70
+ $attributes["Detailed product description"]["Item group ID"]["feed_name"] = "g:item_group_id";
71
+ } else {
72
+ $attributes["Detailed product description"]["Item group ID"]["feed_name"] = "item_group_id";
73
+ }
74
  }
75
  }
76
  ?>
77
+ <div id="dialog" title="Basic dialog">
78
+ <p>
79
+ <div id="dialogText"></div>
80
+ </p>
81
+ </div>
82
 
83
  <div class="wrap">
84
  <div class="woo-product-feed-pro-form-style-2">
124
  foreach($value as $k => $v){
125
  if($v['feed_name'] == $row_v['feed_name']){
126
  if (array_key_exists('name',$v)){
127
+ $dialog_value = $v['feed_name'];
128
  print "<option value='$v[feed_name]' selected>$k ($v[name])</option>";
129
  } else {
130
  print "<option value='$v[feed_name]' selected>$k</option>";
142
  </select>
143
  </td>
144
  <td>
145
+ <?php
146
+ if($row_v['feed_name'] == "g:price"){
147
+ print "<input type='text' name='attributes[$c][prefix]' value='$currency' class='input-field-medium'>";
148
+ } else {
149
+ print "<input type='text' name='attributes[$c][prefix]' class='input-field-medium'>";
150
+ }
151
+ ?>
152
  </td>
153
  <td>
154
  <select name="attributes[<?php print "$c";?>][mapfrom]" class="select-field">
238
  ?>
239
  <input type="hidden" name="project_hash" value="<?php print "$project[project_hash]";?>">
240
  <input type="hidden" name="step" value="100">
241
+ <input type="hidden" name="addrow" id="addrow" value="1">
242
  <input type="button" class="delete-field-mapping" value="- Delete">&nbsp;<input type="button" class="add-field-mapping" value="+ Add field mapping">&nbsp;<input type="button" class="add-own-mapping" value="+ Add custom field">&nbsp;<input type="submit" id="savebutton" value="Save" />
243
 
244
  <?php
246
  ?>
247
  <input type="hidden" name="project_hash" value="<?php print "$project[project_hash]";?>">
248
  <input type="hidden" name="step" value="<?php print "$step";?>">
249
+ <input type="hidden" name="addrow" id="addrow" value="1">
250
  <input type="button" class="delete-field-mapping" value="- Delete">&nbsp;<input type="button" class="add-field-mapping" value="+ Add field mapping">&nbsp;<input type="button" class="add-own-mapping" value="+ Add custom field">&nbsp;<input type="submit" id="savebutton" value="Save" />
251
  <?php
252
  }
pages/admin/woosea-manage-feed.php CHANGED
@@ -23,6 +23,12 @@ $versions = array (
23
  "WooCommerce Product Feed PRO" => WOOCOMMERCESEA_PLUGIN_VERSION
24
  );
25
 
 
 
 
 
 
 
26
  /**
27
  * Change default footer text, asking to review our plugin
28
  **/
@@ -60,7 +66,7 @@ if (!wp_next_scheduled( 'woosea_cron_hook' ) ) {
60
  <?php
61
  if (array_key_exists('debug', $_GET)){
62
  if($_GET['debug'] == "true"){
63
- $external_debug_file = $notifications_obj->woosea_debug_informations ($versions, $product_numbers, $cron_projects);
64
  ?>
65
  <div class="woo-product-feed-pro-form-style-2-heading">Debugging mode</div>
66
  <div class="notice notice-error is-dismissible">
@@ -109,7 +115,7 @@ if (!wp_next_scheduled( 'woosea_cron_hook' ) ) {
109
  $class = "woo-product-feed-pro-strikethrough";
110
  }
111
 
112
- if($val['filename']){
113
  $projectname = ucfirst($val['projectname']);
114
  ?>
115
  <form action="" method="post">
@@ -133,20 +139,20 @@ if (!wp_next_scheduled( 'woosea_cron_hook' ) ) {
133
  ?>
134
  <td>
135
  <div class="actions">
136
- <span class="gear ui-icon ui-icon-gear" id="gear_<?php print "$val[project_hash]";?>" title="project settings"></span>
137
  <?php
138
  if ($val['running'] != "processing"){
139
  ?>
140
  <?php
141
  if ($val['active'] == "true"){
142
- print "<span class=\"ui-icon ui-icon-refresh\" id=\"refresh_$val[project_hash]\" title=\"manually refresh productfeed\"></span>";
143
- print "<a href=\"$val[external_file]\" target=\"_blank\"><span class=\"ui-icon ui-icon-arrowthickstop-1-s\" id=\"download\" title=\"download productfeed\"></span></a>";
144
  }?>
145
- <span class="trash ui-icon ui-icon-trash" id="trash_<?php print "$val[project_hash]";?>" title="delete project and productfeed"></span>
146
 
147
  <?php
148
  } else {
149
- print "<span class=\"ui-icon ui-icon-cancel\" id=\"cancel_$val[project_hash]\" title=\"cancel processing productfeed\"></span>";
150
  }
151
  ?>
152
  </div>
@@ -163,20 +169,20 @@ if (!wp_next_scheduled( 'woosea_cron_hook' ) ) {
163
  <tr>
164
  <td>
165
  <strong>Change settings</strong><br/>
166
- <span class="ui-icon ui-icon-caret-1-e"></span> <a href="admin.php?page=woo-product-feed-pro%2Fwoocommerce-sea.php&action=edit_project&step=0&project_hash=<?php print "$val[project_hash]";?>&channel_hash=<?php print "$val[channel_hash]";?>">General settings</a><br/>
167
  <?php
168
  if ($val['fields'] == "standard"){
169
- print "<span class=\"ui-icon ui-icon-caret-1-e\"></span> <a href=\"admin.php?page=woo-product-feed-pro%2Fwoocommerce-sea.php&action=edit_project&step=2&project_hash=$val[project_hash]&channel_hash=$val[channel_hash]\">Attribute selection</a></br/>";
170
  } else {
171
- print "<span class=\"ui-icon ui-icon-caret-1-e\"></span> <a href=\"admin.php?page=woo-product-feed-pro%2Fwoocommerce-sea.php&action=edit_project&step=7&project_hash=$val[project_hash]&channel_hash=$val[channel_hash]\">Attribute mapping</a><br/>";
172
  }
173
 
174
  if ($val['taxonomy'] != "none"){
175
- print "<span class=\"ui-icon ui-icon-caret-1-e\"></span> <a href=\"admin.php?page=woo-product-feed-pro%2Fwoocommerce-sea.php&action=edit_project&step=1&project_hash=$val[project_hash]&channel_hash=$val[channel_hash]\">Category mapping</a><br/>";
176
  }
177
  ?>
178
- <span class="ui-icon ui-icon-caret-1-e"></span> <a href="admin.php?page=woo-product-feed-pro%2Fwoocommerce-sea.php&action=edit_project&step=4&project_hash=<?php print "$val[project_hash]";?>&channel_hash=<?php print "$val[channel_hash]";?>">Feed filters and rules</a><br/>
179
- <span class="ui-icon ui-icon-caret-1-e"></span> <a href="admin.php?page=woo-product-feed-pro%2Fwoocommerce-sea.php&action=edit_project&step=5&project_hash=<?php print "$val[project_hash]";?>&channel_hash=<?php print "$val[channel_hash]";?>">Conversion tracking and Google Analytis settings</a><br/>
180
  </td>
181
  </tr>
182
  <?php
@@ -187,7 +193,7 @@ if (!wp_next_scheduled( 'woosea_cron_hook' ) ) {
187
  <strong>Feed URL</strong><br/>
188
  <?php
189
  if ($val['active'] == "true"){
190
- print "<span class=\"ui-icon ui-icon-caret-1-e\"></span> $val[external_file]";
191
  } else {
192
  print "<span class=\"ui-icon ui-icon-alert\"></span> Whoops, there is no active product feed for this project as the project has been disabled.";
193
  }
@@ -226,24 +232,71 @@ if (!wp_next_scheduled( 'woosea_cron_hook' ) ) {
226
  </table><br/>
227
  -->
228
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
  <table class="woo-product-feed-pro-table">
230
  <tr>
231
- <td><strong>We’ve got you covered!</strong></td>
232
  </tr>
233
  <tr>
234
  <td>
235
- Need assistance? Check out our:
236
  <ul>
237
- <li><strong><a href="https://adtribes.io/support/" target="_blank">F.A.Q.</a></strong></li>
238
- <li><strong><a href="https://www.youtube.com/channel/UCXp1NsK-G_w0XzkfHW-NZCw" target="_blank">YouTube tutorials</a></strong></li>
 
239
  </ul>
240
- Or just reach out to us at <a href="mailto:support@adtribes.io">support@adtribes.io</a> and we'll make sure your product feeds will be up-and-running within no-time.
241
  </td>
242
  </tr>
243
- </table>
244
-
245
 
246
 
 
 
 
 
 
 
 
 
 
 
247
  </div>
248
  </div>
249
  </tbody>
23
  "WooCommerce Product Feed PRO" => WOOCOMMERCESEA_PLUGIN_VERSION
24
  );
25
 
26
+ // Get the sales from created product feeds
27
+ global $wpdb;
28
+ $charset_collate = $wpdb->get_charset_collate();
29
+ $table_name = $wpdb->prefix . 'adtribes_my_conversions';
30
+ $order_rows = $wpdb->get_results("SELECT * FROM $table_name", ARRAY_A);
31
+
32
  /**
33
  * Change default footer text, asking to review our plugin
34
  **/
66
  <?php
67
  if (array_key_exists('debug', $_GET)){
68
  if($_GET['debug'] == "true"){
69
+ $external_debug_file = $notifications_obj->woosea_debug_informations ($versions, $product_numbers, $order_rows, $cron_projects);
70
  ?>
71
  <div class="woo-product-feed-pro-form-style-2-heading">Debugging mode</div>
72
  <div class="notice notice-error is-dismissible">
115
  $class = "woo-product-feed-pro-strikethrough";
116
  }
117
 
118
+ if(isset($val['filename'])){
119
  $projectname = ucfirst($val['projectname']);
120
  ?>
121
  <form action="" method="post">
139
  ?>
140
  <td>
141
  <div class="actions">
142
+ <span class="gear ui-icon ui-icon-gear" id="gear_<?php print "$val[project_hash]";?>" title="project settings" style="display: inline-block;"></span>
143
  <?php
144
  if ($val['running'] != "processing"){
145
  ?>
146
  <?php
147
  if ($val['active'] == "true"){
148
+ print "<span class=\"ui-icon ui-icon-refresh\" id=\"refresh_$val[project_hash]\" title=\"manually refresh productfeed\" style=\"display: inline-block;\"></span>";
149
+ print "<a href=\"$val[external_file]\" target=\"_blank\"><span class=\"ui-icon ui-icon-arrowthickstop-1-s\" id=\"download\" title=\"download productfeed\" style=\"display: inline-block\"></span></a>";
150
  }?>
151
+ <span class="trash ui-icon ui-icon-trash" id="trash_<?php print "$val[project_hash]";?>" title="delete project and productfeed" style="display: inline-block;"></span>
152
 
153
  <?php
154
  } else {
155
+ print "<span class=\"ui-icon ui-icon-cancel\" id=\"cancel_$val[project_hash]\" title=\"cancel processing productfeed\" style=\"display: inline-block;\"></span>";
156
  }
157
  ?>
158
  </div>
169
  <tr>
170
  <td>
171
  <strong>Change settings</strong><br/>
172
+ <span class="ui-icon ui-icon-caret-1-e" style="display: inline-block;"></span> <a href="admin.php?page=woo-product-feed-pro%2Fwoocommerce-sea.php&action=edit_project&step=0&project_hash=<?php print "$val[project_hash]";?>&channel_hash=<?php print "$val[channel_hash]";?>">General settings</a><br/>
173
  <?php
174
  if ($val['fields'] == "standard"){
175
+ print "<span class=\"u-icon ui-icon-caret-1-e\" style=\"display: inline-block;\"></span> <a href=\"admin.php?page=woo-product-feed-pro%2Fwoocommerce-sea.php&action=edit_project&step=2&project_hash=$val[project_hash]&channel_hash=$val[channel_hash]\">Attribute selection</a></br/>";
176
  } else {
177
+ print "<span class=\"ui-icon ui-icon-caret-1-e\" style=\"display: inline-block;\"></span> <a href=\"admin.php?page=woo-product-feed-pro%2Fwoocommerce-sea.php&action=edit_project&step=7&project_hash=$val[project_hash]&channel_hash=$val[channel_hash]\">Attribute mapping</a><br/>";
178
  }
179
 
180
  if ($val['taxonomy'] != "none"){
181
+ print "<span class=\"ui-icon ui-icon-caret-1-e\" style=\"display: inline-block;\"></span> <a href=\"admin.php?page=woo-product-feed-pro%2Fwoocommerce-sea.php&action=edit_project&step=1&project_hash=$val[project_hash]&channel_hash=$val[channel_hash]\">Category mapping</a><br/>";
182
  }
183
  ?>
184
+ <span class="ui-icon ui-icon-caret-1-e" style="display: inline-block;"></span> <a href="admin.php?page=woo-product-feed-pro%2Fwoocommerce-sea.php&action=edit_project&step=4&project_hash=<?php print "$val[project_hash]";?>&channel_hash=<?php print "$val[channel_hash]";?>">Feed filters and rules</a><br/>
185
+ <span class="ui-icon ui-icon-caret-1-e" style="display: inline-block;"></span> <a href="admin.php?page=woo-product-feed-pro%2Fwoocommerce-sea.php&action=edit_project&step=5&project_hash=<?php print "$val[project_hash]";?>&channel_hash=<?php print "$val[channel_hash]";?>">Conversion tracking and Google Analytics settings</a><br/>
186
  </td>
187
  </tr>
188
  <?php
193
  <strong>Feed URL</strong><br/>
194
  <?php
195
  if ($val['active'] == "true"){
196
+ print "<span class=\"ui-icon ui-icon-caret-1-e\" style=\"display: inline-block;\"></span> $val[external_file]";
197
  } else {
198
  print "<span class=\"ui-icon ui-icon-alert\"></span> Whoops, there is no active product feed for this project as the project has been disabled.";
199
  }
232
  </table><br/>
233
  -->
234
 
235
+
236
+ <table class="woo-product-feed-pro-table">
237
+ <tr>
238
+ <td><strong>We’ve got you covered!</strong></td>
239
+ </tr>
240
+ <tr>
241
+ <td>
242
+ Need assistance? Check out our:
243
+ <ul>
244
+ <li><strong><a href="https://adtribes.io/support/" target="_blank">Frequently Asked Questions</a></strong></li>
245
+ <li><strong><a href="https://www.youtube.com/channel/UCXp1NsK-G_w0XzkfHW-NZCw" target="_blank">YouTube tutorials</a></strong></li>
246
+ <li><strong><a href="https://adtribes.io/blog/" target="_blank">Blog</a></strong></li>
247
+ <li><strong><a href="https://adtribes.io/pro-vs-elite/?utm_source=$domain&utm_medium=plugin&utm_campaign=upgrade-elite" target="_blank">Upgrade to Elite</a></strong></li>
248
+ </ul>
249
+ Or just reach out to us at <strong><a href="https://wordpress.org/support/plugin/woo-product-feed-pro/" target="_blank">the support forum</a></strong> and we'll make sure your product feeds will be up-and-running within no-time.
250
+ </td>
251
+ </tr>
252
+ </table><br/>
253
+
254
+ <table class="woo-product-feed-pro-table">
255
+ <tr>
256
+ <td><strong>Why upgrade to Elite?</strong></td>
257
+ </tr>
258
+ <tr>
259
+ <td>
260
+ Enjoy all priviliges of our Elite features and priority support and upgrade to the Elite version of our plugin now!
261
+ <ul>
262
+ <li><strong>1.</strong> More products approved by Google</li>
263
+ <li><strong>2.</strong> Add GTIN, brand and more fields to your store</li>
264
+ <li><strong>3.</strong> Exclude individual products from your feeds</li>
265
+ <li><strong>4.</strong> Priority support</li>
266
+ </ul>
267
+ <strong>
268
+ <a href="https://adtribes.io/pro-vs-elite/?utm_source=$domain&utm_medium=plugin&utm_campaign=upgrade-elite" target="_blank">Upgrade to Elite here!</a>
269
+ </strong>
270
+ </td>
271
+ </tr>
272
+ </table><br/>
273
+
274
  <table class="woo-product-feed-pro-table">
275
  <tr>
276
+ <td><strong>Our latest blog articles</strong></td>
277
  </tr>
278
  <tr>
279
  <td>
 
280
  <ul>
281
+ <li><strong>1. <a href="https://adtribes.io/add-gtin-mpn-upc-ean-product-condition-optimised-title-and-brand-attributes/" target="_blank">Adding GTIN, Brand, MPN and more</a></strong></li>
282
+ <li><strong>2. <a href="https://adtribes.io/woocommerce-structured-data-bug/" target="_blank">WooCommerce structured data markup bug</a></strong></li>
283
+ <li><strong>3. <a href="https://adtribes.io/how-to-create-filters-for-your-product-feed/" target="_blank">How to create filters for your product feed</a></strong></li>
284
  </ul>
 
285
  </td>
286
  </tr>
287
+ </table><br/>
 
288
 
289
 
290
+ <table class="woo-product-feed-pro-table">
291
+ <tr>
292
+ <td><strong>WooCommerce product numbers</strong></td>
293
+ </tr>
294
+ <tr>
295
+ <td>
296
+ You currently have <strong><?php print "$published_products";?></strong> published products on your website out of which <strong><?php print "$published_single";?></strong> are single products and <strong><?php print "$published_variation";?></strong> are variable products.
297
+ </td>
298
+ </tr>
299
+ </table>
300
  </div>
301
  </div>
302
  </tbody>
pages/admin/woosea-manage-settings.php CHANGED
@@ -1,7 +1,9 @@
1
  <?php
 
2
  $plugin_settings = get_option( 'plugin_settings' );
 
3
  $error = "false";
4
-
5
  $plugin_data = get_plugin_data( __FILE__ );
6
 
7
  $versions = array (
@@ -42,6 +44,13 @@ if (!wp_next_scheduled( 'woosea_cron_hook' ) ) {
42
  $notifications_box = $notifications_obj->get_admin_notifications ( '12', 'false' );
43
  }
44
  ?>
 
 
 
 
 
 
 
45
  <div class="wrap">
46
  <div class="woo-product-feed-pro-form-style-2">
47
  <tbody class="woo-product-feed-pro-body">
@@ -58,11 +67,14 @@ if (!wp_next_scheduled( 'woosea_cron_hook' ) ) {
58
 
59
  <form action="" method="post">
60
  <tr>
61
- <td><span>Grant access to AdTribes.io support:</span></td>
 
 
62
  <td>
63
  <label class="woo-product-feed-pro-switch">
64
  <?php
65
- if(isset($plugin_settings['grant_access'])){
 
66
  print "<input type=\"checkbox\" id=\"grant_access\" name=\"grant_access\" class=\"checkbox-field\" checked>";
67
  } else {
68
  print "<input type=\"checkbox\" id=\"grant_access\" name=\"grant_access\" class=\"checkbox-field\">";
@@ -72,41 +84,118 @@ if (!wp_next_scheduled( 'woosea_cron_hook' ) ) {
72
  </label>
73
  </td>
74
  </tr>
75
- <!--
76
  <tr>
77
- <td><span>Batch-size products processing:</span></td>
78
  <td>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  <?php
80
- if(isset($plugin_settings['batch_size'])){
81
- print "<input type=\"text\" class=\"input-field-small\" name=\"batch_size\" value=\"$plugin_settings[batch_size]\"> products per batch";
82
- } else {
83
- print "<input type=\"text\" class=\"input-field-small\" name=\"batch_size\" value=\"250\"> products per batch";
84
- }
 
85
  ?>
 
 
86
  </td>
87
  </tr>
88
- -->
89
  </form>
90
  </table>
91
  </div>
92
 
93
  <div class="woo-product-feed-pro-table-right">
94
- <table class="woo-product-feed-pro-table">
95
- <tr>
96
- <td><strong>We’ve got you covered!</strong></td>
97
- </tr>
98
-
99
- <tr>
100
- <td>
 
101
  Need assistance? Check out our:
102
  <ul>
103
- <li><strong><a href="https://adtribes.io/support/" target="_blank">F.A.Q.</a></strong></li>
104
  <li><strong><a href="https://www.youtube.com/channel/UCXp1NsK-G_w0XzkfHW-NZCw" target="_blank">YouTube tutorials</a></strong></li>
 
 
105
  </ul>
106
- Or just reach out to us at <a href="mailto:support@adtribes.io">support@adtribes.io</a> and we'll make sure your product feeds will be up-and-running within no-time.
107
- </td>
108
- </tr>
109
- </table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  </div>
111
  </div>
112
  </tbody>
1
  <?php
2
+ $domain = $_SERVER['HTTP_HOST'];
3
  $plugin_settings = get_option( 'plugin_settings' );
4
+ $license_information = get_option( 'license_information' );
5
  $error = "false";
6
+ $disabled = "";
7
  $plugin_data = get_plugin_data( __FILE__ );
8
 
9
  $versions = array (
44
  $notifications_box = $notifications_obj->get_admin_notifications ( '12', 'false' );
45
  }
46
  ?>
47
+
48
+ <div id="dialog" title="Basic dialog">
49
+ <p>
50
+ <div id="dialogText"></div>
51
+ </p>
52
+ </div>
53
+
54
  <div class="wrap">
55
  <div class="woo-product-feed-pro-form-style-2">
56
  <tbody class="woo-product-feed-pro-body">
67
 
68
  <form action="" method="post">
69
  <tr>
70
+ <td>
71
+ <span>Grant access to AdTribes.io support:</span>
72
+ </td>
73
  <td>
74
  <label class="woo-product-feed-pro-switch">
75
  <?php
76
+ $woosea_support_user = get_option('woosea_support_user');
77
+ if($woosea_support_user == "yes"){
78
  print "<input type=\"checkbox\" id=\"grant_access\" name=\"grant_access\" class=\"checkbox-field\" checked>";
79
  } else {
80
  print "<input type=\"checkbox\" id=\"grant_access\" name=\"grant_access\" class=\"checkbox-field\">";
84
  </label>
85
  </td>
86
  </tr>
87
+
88
  <tr>
 
89
  <td>
90
+ <span>Increase the number of products that will be approved in Google's Merchant Center:<br/>
91
+ This option will fix WooCommerce's (JSON-LD) structured data bug and add extra structured data elements to your pages (<a href="https://adtribes.io/woocommerce-structured-data-bug/" target="_blank">Read more about this)</a></span>
92
+ <?php
93
+ if ($license_information['license_valid'] == "false"){
94
+ print "<span><a href=\"https://adtribes.io/pro-vs-elite/?utm_source=$domain&utm_medium=plugin&utm_campaign=upgrade-elite\" target=\"_blank\">Upgrade to Elite</a> to activate this feature</span>";
95
+ $disabled = "disabled";
96
+ }
97
+ ?>
98
+ </td>
99
+ <td>
100
+ <label class="woo-product-feed-pro-switch">
101
+ <?php
102
+ $structured_data_fix = get_option ('structured_data_fix');
103
+ if($structured_data_fix == "yes"){
104
+ print "<input type=\"checkbox\" id=\"fix_json_ld\" name=\"fix_json_ld\" class=\"checkbox-field\" checked $disabled>";
105
+ } else {
106
+ print "<input type=\"checkbox\" id=\"fix_json_ld\" name=\"fix_json_ld\" class=\"checkbox-field\" $disabled>";
107
+ }
108
+ ?>
109
+ <div class="woo-product-feed-pro-slider round"></div>
110
+ </label>
111
+ </td>
112
+ </tr>
113
+
114
+ <tr>
115
+ <td>
116
+ <span>Add GTIN, MPN, UPC, EAN, Product condition, Optimised title and Brand attributes to your store: (<a href="https://adtribes.io/add-gtin-mpn-upc-ean-product-condition-optimised-title-and-brand-attributes/" target="_blank">Read more about this)</a></span>
117
+ <?php
118
+ if ($license_information['license_valid'] == "false"){
119
+ print "<span><a href=\"https://adtribes.io/pro-vs-elite/?utm_source=$domain&utm_medium=plugin&utm_campaign=upgrade-elite\" target=\"_blank\">Upgrade to Elite</a> to activate this feature</span>";
120
+ }
121
+ ?>
122
+ </td>
123
+ <td>
124
+ <label class="woo-product-feed-pro-switch">
125
  <?php
126
+ $add_unique_identifiers = get_option ('add_unique_identifiers');
127
+ if($add_unique_identifiers == "yes"){
128
+ print "<input type=\"checkbox\" id=\"add_identifiers\" name=\"add_identifiers\" class=\"checkbox-field\" checked $disabled>";
129
+ } else {
130
+ print "<input type=\"checkbox\" id=\"add_identifiers\" name=\"add_identifiers\" class=\"checkbox-field\" $disabled>";
131
+ }
132
  ?>
133
+ <div class="woo-product-feed-pro-slider round"></div>
134
+ </label>
135
  </td>
136
  </tr>
 
137
  </form>
138
  </table>
139
  </div>
140
 
141
  <div class="woo-product-feed-pro-table-right">
142
+
143
+
144
+ <table class="woo-product-feed-pro-table">
145
+ <tr>
146
+ <td><strong>We’ve got you covered!</strong></td>
147
+ </tr>
148
+ <tr>
149
+ <td>
150
  Need assistance? Check out our:
151
  <ul>
152
+ <li><strong><a href="https://adtribes.io/support/" target="_blank">Frequently Asked Questions</a></strong></li>
153
  <li><strong><a href="https://www.youtube.com/channel/UCXp1NsK-G_w0XzkfHW-NZCw" target="_blank">YouTube tutorials</a></strong></li>
154
+ <li><strong><a href="https://adtribes.io/blog/" target="_blank">Blog</a></strong></li>
155
+ <li><strong><a href="https://adtribes.io/pro-vs-elite/?utm_source=$domain&utm_medium=plugin&utm_campaign=upgrade-elite" target="_blank">Upgrade to Elite</a></strong></li>
156
  </ul>
157
+ Or just reach out to us at <strong><a href="https://wordpress.org/support/plugin/woo-product-feed-pro/" target="_blank">the support forum</a></strong> and we'll make sure your product feeds will be up-and-running within no-time.
158
+ </td>
159
+ </tr>
160
+ </table><br/>
161
+
162
+ <table class="woo-product-feed-pro-table">
163
+ <tr>
164
+ <td><strong>Why upgrade to Elite?</strong></td>
165
+ </tr>
166
+ <tr>
167
+ <td>
168
+ Enjoy all priviliges of our Elite features and priority support and upgrade to the Elite version of our plugin now!
169
+ <ul>
170
+ <li><strong>1.</strong> More products approved by Google </li>
171
+ <li><strong>2.</strong> Add GTIN, brand and more fields to your store</li>
172
+ <li><strong>3.</strong> Exclude individual products from your feeds</li>
173
+ <li><strong>4.</strong> Priority support</li>
174
+ </ul>
175
+ <strong>
176
+ <a href="https://adtribes.io/pro-vs-elite/?utm_source=$domain&utm_medium=plugin&utm_campaign=upgrade-elite" target="_blank">Upgrade to Elite here!</a>
177
+ </strong>
178
+ </td>
179
+ </tr>
180
+ </table><br/>
181
+
182
+
183
+ <table class="woo-product-feed-pro-table">
184
+ <tr>
185
+ <td><strong>Our latest blog articles</strong></td>
186
+ </tr>
187
+ <tr>
188
+ <td>
189
+ <ul>
190
+ <li><strong>1. <a href="https://adtribes.io/add-gtin-mpn-upc-ean-product-condition-optimised-title-and-brand-attributes/" target="_blank">Adding GTIN, Brand, MPN and more</a></strong></li>
191
+ <li><strong>2. <a href="https://adtribes.io/woocommerce-structured-data-bug/" target="_blank">WooCommerce structured data markup bug</a></strong></li>
192
+ <li><strong>3. <a href="https://adtribes.io/how-to-create-filters-for-your-product-feed/" target="_blank">How to create filters for your product feed</a></strong></li>
193
+ </ul>
194
+ </td>
195
+ </tr>
196
+ </table><br/>
197
+
198
+
199
  </div>
200
  </div>
201
  </tbody>
pages/admin/woosea-upgrade-elite.php ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ $plugin_settings = get_option( 'plugin_settings' );
3
+ $license_information = get_option( 'license_information' );
4
+ $domain = $_SERVER['HTTP_HOST'];
5
+ $error = "false";
6
+ $plugin_data = get_plugin_data( __FILE__ );
7
+
8
+ $versions = array (
9
+ "PHP" => (float)phpversion(),
10
+ "Wordpress" => get_bloginfo('version'),
11
+ "WooCommerce" => WC()->version,
12
+ "WooCommerce Product Feed PRO" => WOOCOMMERCESEA_PLUGIN_VERSION
13
+ );
14
+
15
+ // When license has not been checked yet
16
+ if(empty($license_information['message'])){
17
+ $license_information['message'] = "You did not purchase a license for our Elite features yet. The structured data fix feature and adding of extra Google Shopping fields to your store can be enabled if you upgrade. Please purchase a license key on <a href=\"https://adtribes.io/pro-vs-elite/?utm_source=$domain&utm_medium=plugin&utm_campaign=upgrade-elite\" target=\"_blank\">AdTribes.io</a> when you would like to use the Elite features.";
18
+ $license_information['message_type'] = "notice notice-info is-dismissible";
19
+ $license_information['license_key'] = "";
20
+ $license_information['license_email'] = "";
21
+ }
22
+
23
+
24
+ /**
25
+ * Change default footer text, asking to review our plugin
26
+ **/
27
+ function my_footer_text($default) {
28
+ return 'If you like our <strong>WooCommerce Product Feed PRO</strong> plugin please leave us a <a href="https://wordpress.org/support/plugin/woo-product-feed-pro/reviews?rate=5#new-post" target="_blank" class="woo-product-feed-pro-ratingRequest">&#9733;&#9733;&#9733;&#9733;&#9733;</a> rating. Thanks in advance!';
29
+ }
30
+ add_filter('admin_footer_text', 'my_footer_text');
31
+
32
+ /**
33
+ * Create notification object and get message and message type as WooCommerce is inactive
34
+ * also set variable allowed on 0 to disable submit button on step 1 of configuration
35
+ */
36
+ $notifications_obj = new WooSEA_Get_Admin_Notifications;
37
+ if (!in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
38
+ $notifications_box = $notifications_obj->get_admin_notifications ( '9', 'false' );
39
+ } else {
40
+ $notifications_box = $notifications_obj->get_admin_notifications ( '14', 'false' );
41
+ }
42
+
43
+ if ($versions['PHP'] < 5.6){
44
+ $notifications_box = $notifications_obj->get_admin_notifications ( '11', 'false' );
45
+ }
46
+
47
+ if ($versions['WooCommerce'] < 3){
48
+ $notifications_box = $notifications_obj->get_admin_notifications ( '13', 'false' );
49
+ }
50
+
51
+ if (!wp_next_scheduled( 'woosea_cron_hook' ) ) {
52
+ $notifications_box = $notifications_obj->get_admin_notifications ( '12', 'false' );
53
+ }
54
+ ?>
55
+
56
+ <div id="dialog" title="Basic dialog">
57
+ <p>
58
+ <div id="dialogText"></div>
59
+ </p>
60
+ </div>
61
+
62
+ <div class="wrap">
63
+ <div class="woo-product-feed-pro-form-style-2">
64
+ <tbody class="woo-product-feed-pro-body">
65
+ <div class="woo-product-feed-pro-form-style-2-heading">Upgrade to Elite</div>
66
+ <div class="<?php _e($license_information['message_type']); ?>">
67
+ <p><?php _e($license_information['message'], 'sample-text-domain' ); ?></p>
68
+ </div>
69
+
70
+ <div class="woo-product-feed-pro-table-wrapper">
71
+ <div class="woo-product-feed-pro-table-left">
72
+
73
+ <table class="woo-product-feed-pro-table">
74
+ <tr>
75
+ <td>
76
+ <span>License e-mail:</span>
77
+ </td>
78
+ <td>
79
+ <input type="text" class="input-field-large" id="license-email" name="license-email" value="<?php print "$license_information[license_email]";?>">
80
+ </td>
81
+ </tr>
82
+ <tr>
83
+ <td>
84
+ <span>License key:</span>
85
+ </td>
86
+ <td>
87
+ <input type="text" class="input-field-large" id="license-key" name="license-key" value="<?php print "$license_information[license_key]";?>">
88
+ </td>
89
+ </tr>
90
+ <tr>
91
+ <td colspan="2"><i>Please note that we will automatically validate your license twice a day.</i></td>
92
+ </tr>
93
+ <tr>
94
+ <td colspan="2">
95
+ <input type="submit" id="checklicense" value="Activate license">
96
+ <input type="submit" id="deactivate_license" value="Deactivate license">
97
+ </td>
98
+ </tr>
99
+
100
+ </table>
101
+ </div>
102
+
103
+ <div class="woo-product-feed-pro-table-right">
104
+
105
+ <table class="woo-product-feed-pro-table">
106
+ <tr>
107
+ <td><strong>Why upgrade to Elite?</strong></td>
108
+ </tr>
109
+ <tr>
110
+ <td>
111
+ Enjoy all priviliges of our Elite features and priority support and upgrade to the Elite version of our plugin now!
112
+ <ul>
113
+ <li><strong>1.</strong> More products approved by Google </li>
114
+ <li><strong>2.</strong> Add GTIN, brand and more fields to your store</li>
115
+ <li><strong>3.</strong> Exclude individual products from your feeds</li>
116
+ <li><strong>4.</strong> Priority support</li>
117
+ </ul>
118
+ <strong>
119
+ <a href="https://adtribes.io/pro-vs-elite/?utm_source=$domain&utm_medium=plugin&utm_campaign=upgrade-elite" target="_blank">Upgrade to Elite here!</a>
120
+ </strong>
121
+ </td>
122
+ </tr>
123
+ </table><br/>
124
+
125
+ <table class="woo-product-feed-pro-table">
126
+ <tr>
127
+ <td><strong>We’ve got you covered!</strong></td>
128
+ </tr>
129
+ <tr>
130
+ <td>
131
+ Need assistance? Check out our:
132
+ <ul>
133
+ <li><strong><a href="https://adtribes.io/support/" target="_blank">Frequently Asked Questions</a></strong></li>
134
+ <li><strong><a href="https://www.youtube.com/channel/UCXp1NsK-G_w0XzkfHW-NZCw" target="_blank">YouTube tutorials</a></strong></li>
135
+ <li><strong><a href="https://adtribes.io/blog/" target="_blank">Blog</a></strong></li>
136
+ <li><strong><a href="https://adtribes.io/pro-vs-elite/?utm_source=$domain&utm_medium=plugin&utm_campaign=upgrade-elite" target="_blank">Upgrade to Elite</a></strong></li>
137
+ </ul>
138
+ Or just reach out to us at <strong><a href="https://wordpress.org/support/plugin/woo-product-feed-pro/" target="_blank">the support forum</a></strong> and we'll make sure your product feeds will be up-and-running within no-time.
139
+ </td>
140
+ </tr>
141
+ </table><br/>
142
+
143
+ <table class="woo-product-feed-pro-table">
144
+ <tr>
145
+ <td><strong>Our latest blog articles</strong></td>
146
+ </tr>
147
+ <tr>
148
+ <td>
149
+ <ul>
150
+ <li><strong>1. <a href="https://adtribes.io/add-gtin-mpn-upc-ean-product-condition-optimised-title-and-brand-attributes/" target="_blank">Adding GTIN, Brand, MPN and more</a></strong></li>
151
+ <li><strong>2. <a href="https://adtribes.io/woocommerce-structured-data-bug/" target="_blank">WooCommerce structured data markup bug</a></strong></li>
152
+ <li><strong>3. <a href="https://adtribes.io/how-to-create-filters-for-your-product-feed/" target="_blank">How to create filters for your product feed</a></strong></li>
153
+ </ul>
154
+ </td>
155
+ </tr>
156
+ </table><br/>
157
+
158
+ </div>
159
+ </div>
160
+ </tbody>
161
+ </div>
162
+ </div>
readme.txt CHANGED
@@ -1,16 +1,16 @@
1
- === WooCommerce Product Feed PRO ===
2
- Contributors: jorisverwater
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=j_verwater%40hotmail%2ecom&lc=NL&item_name=Donation%20WooCommerce%20Product%20Feed%20Pro%20%2d%20AdTribes%2eio&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted
4
  License: GPLv3
5
  License URI: http://www.gnu.org/licenses/gpl.html
6
- Tags: Product Feed, Google Shopping, Google Shopping Feed, WooCommerce Product Feed, WooCommerce Product Feed PRO, Bing Shopping, Bing product feed, Bing remarking, Google Merchant Feed, Google DRM Feed, Google Dynamic Remarketing Feed, Facebook feed, Google feed, Bing feed, Facebook Product Feed, Facebook Dynamic remarketing, Data Feed, WooCommerce Feed, XML product feed, CSV product feed, TXT product feed, comparison shopping engines, comparison shopping websites, vergelijk.nl, vergelijk.be, vertaa.fi, beslist.nl, kieskeurig.nl, bol.com, raketten, pricerunner, pricegrabber, Buy, leGuide, Kelkoo, Twenga, Yandex, Etsy, Dealtime, Shopzilla, Billiger
7
  Requires at least: 4.5
8
  Tested up to: 4.9
9
- Stable tag: 2.0.0
10
 
11
  == Description ==
12
 
13
- Generate WooCommerce product feeds for all your marketing channels, such as Google Shopping, Google Dynamic Remarketing, Facebook Remarketing, Bing Ads, Billiger.de, Pricerunner, Vergelijk.nl and many more. Next to custom feeds there are over 100 pre-defined templates included for marketplaces, comparison shopping engines and search engines.
14
 
15
  = Why choose this plugin? =
16
  Simply because this is the most complete plugin offering support for an unlimited number of products and feeds, including features such as category- & field-mapping and advanced, rule-based, filtering and product variables support.
@@ -35,6 +35,12 @@ Determine yourself what attributes to in- or exclude in your product feed. This
35
  = Field / attribute mapping =
36
  Map your field attributes to those of the channels of your choice. For many channels using the right field names is obliged.
37
 
 
 
 
 
 
 
38
  = Conversion tracking =
39
  As of version 1.8.8 the plugin is able to track sales and conversions coming from your product feeds. Just enable the 'conversion tracking' and the plugin will measure how much turn-over is coming from your marketing campaigns. The plugin uses both session- and cookie-conversions to make sure all sales are tracked.
40
 
@@ -47,6 +53,9 @@ Add static field values to your product feed when needed.
47
  = Category / taxonomy mapping =
48
  Some marketing channels require you to map your categories to theirs (such as Google Shopping). This plugin enables you to exactly do that. Not only does it support 1-to-1 category mapping but you can also map subsets of products on a channel-category based on product names.
49
 
 
 
 
50
  = Google Analytics support =
51
  This plugin enables you to add and configure Google Analytics UTM tracking-codes to your product URL’s so you can measure the effectiveness of your marketing channels in Google Analytics.
52
 
@@ -70,12 +79,12 @@ Product feed statistics showing you the amount of products in yor product feed a
70
  * Unlimited number of product feeds
71
  * > 100 pre-configured product feed channel-templates for ~ 200 countries;
72
  * Create custom product feeds;
73
- * XML, CSV and TXT formats;
74
  * Tracks conversions and sales;
75
  * Intuitive interface;
76
  * Supports product variations / variables;
77
  * Scheduled product feed refreshes: daily, twice-daily or every hour;
78
- * Supported file formats: XML, TXT and CSV;
79
  * Supports shipping zones, shipping classes and shipping cost
80
  * Filters and rules: set product filter and rules so only the right products end up in the product feed;
81
  * Category / Taxonomy mapping: map your categories to those of other channels, such as Google Shopping;
@@ -86,11 +95,13 @@ Product feed statistics showing you the amount of products in yor product feed a
86
  * Supports the official Facebook for WooCommerce plugin (SKU_ID parameter)
87
  * Supports Yoasts primary category feature
88
  * Supports Yith brand attributes
 
89
 
90
  === Channels ===
91
  * Custom feeds
92
  * Google Shopping
93
  * Google DRM / Dynamic remarketing
 
94
  * Facebook Dynamic Ad’s / remarketing
95
  * Bing Shopping
96
  * <a href="https://yandex.com/support/market-tech-requirements/index.html" target="_blank">Yandex</a>
@@ -103,12 +114,12 @@ Product feed statistics showing you the amount of products in yor product feed a
103
  * <a href="https://www.comparer.be" target="_blank">Comparer.be</a>
104
  * Kieskeurig.nl
105
  * Kieskeurig.be
106
- * Beslist.nl
107
- * Beslist.be
108
  * Bol.com
109
  * Stylight
110
  * Incurvy
111
- * Kijiji
112
  * Kelkoo
113
  * <a href="https://www.zbozi.cz" target="_blank">Zbozi.cz</a>
114
  * Shopalike
@@ -160,6 +171,7 @@ Product feed statistics showing you the amount of products in yor product feed a
160
  * Trovaprezzi
161
  * Tweakers.nl
162
  * Kleding.nl
 
163
 
164
  == Installation ==
165
 
@@ -237,6 +249,287 @@ Questions left or unanswered? Please do not hesitate to contact us at support@ad
237
 
238
  === Changelog ===
239
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240
  = 2.0.0 (2018-18-01) =
241
  * Added a new field "Category path". This field shows the so-called breadcrumb and can be used for your productfeed (needed for Prisjakt)
242
 
@@ -256,7 +549,7 @@ Questions left or unanswered? Please do not hesitate to contact us at support@ad
256
  * Fixed a bug: additional gallery images are now also shown in Custom XML feeds
257
 
258
  = 1.9.4 (2018-05-01) =
259
- * Fixed a bug: additional gallery images are now also shown in XML and Google Shopping feeds
260
 
261
  = 1.9.3 (2018-05-01) =
262
  * Added the possibility map products on Google Shopping categories based on advanced rules. You can now map your products to Google Shopping categories not only based on the product category but on any product attribute.
@@ -541,6 +834,288 @@ Questions left or unanswered? Please do not hesitate to contact us at support@ad
541
 
542
  == Upgrade Notice ==
543
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
544
  = 2.0.0 =
545
  Added the category path field which can be used to show the category path or so called breadcrumn in your product feeds
546
 
1
+ === WooCommerce Product Feed Plugin PRO for Google Shopping, Facebook and many more - AdTribes.io ===
2
+ Contributors: jorisverwater,evavangelooven
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=j_verwater%40hotmail%2ecom&lc=NL&item_name=Donation%20WooCommerce%20Product%20Feed%20Pro%20%2d%20AdTribes%2eio&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted
4
  License: GPLv3
5
  License URI: http://www.gnu.org/licenses/gpl.html
6
+ Tags: Product Feed, Google Shopping, Google Shopping Feed, WooCommerce Product Feed, WooCommerce Product Feed PRO, Bing Shopping, Bing product feed, Bing remarking, Google Merchant Feed, Google DRM Feed, Google Dynamic Remarketing Feed, Facebook feed, Google feed, Bing feed, Facebook Product Feed, Facebook Dynamic remarketing, Data Feed, WooCommerce Feed, XML product feed, CSV product feed, TSV, TXT product feed, comparison shopping engines, comparison shopping websites, vergelijk.nl, vergelijk.be, vertaa.fi, beslist.nl, kieskeurig.nl, bol.com, raketten, pricerunner, pricegrabber, Buy, leGuide, Kelkoo, Twenga, Yandex, Etsy, Dealtime, Shopzilla, Billiger
7
  Requires at least: 4.5
8
  Tested up to: 4.9
9
+ Stable tag: 3.0.0
10
 
11
  == Description ==
12
 
13
+ Generate WooCommerce product feeds for all your marketing channels, such as Google Shopping (merchant center), Google Dynamic Remarketing, Facebook Remarketing, Bing Ads, Billiger.de, Pricerunner, Vergelijk.nl and many more. Next to custom feeds there are over 100 pre-defined templates included for marketplaces, comparison shopping engines and search engines. This plugin provides high-quality product feed for Google Shopping and many many more.
14
 
15
  = Why choose this plugin? =
16
  Simply because this is the most complete plugin offering support for an unlimited number of products and feeds, including features such as category- & field-mapping and advanced, rule-based, filtering and product variables support.
35
  = Field / attribute mapping =
36
  Map your field attributes to those of the channels of your choice. For many channels using the right field names is obliged.
37
 
38
+ = Fix for WooCommerce structured data bug =
39
+ Because of a bug in WooCommerce variable products will get disapproved in Google's Merchant Center. WooCommerce adds the price of the cheapest variable product in the structured data for all variations of a product. Because of this there will be a mismatch between the product price you provide to Google in your Google Shopping product feed and the structured data price on the product landingpage. Google will therefor disapprove the product in its merchant center. You won't be able to advertise on that product in your Google Shopping campaign. Our plugin has a feature that will fix the structured data on variable product pages by adding the correct variable product price in the JSON-LD structured data so Google will approve the variable products you submitted. This feature is only available to plugin users who upgraded to the paid Elite version of the plugin.
40
+
41
+ = Add critical Google Shopping Feed fields to your store =
42
+ Google requires you to add certain fields to the feed you create for Google Shopping. However not all of the required fields are present in WooCommerce. Our plugin add's these fields / attributes for you so you can create a product feed that meets Google's requirements. The plugin will add the following product input fields for you: Brand, GTIN, UPC, MPN, EAN, Product condition (New, Refurbished, Used) unit pricing measure, unit pricing base measure and an Optimised title field. This feature is only available to plugin users who upgraded to the paid Elite version of the plugin.
43
+
44
  = Conversion tracking =
45
  As of version 1.8.8 the plugin is able to track sales and conversions coming from your product feeds. Just enable the 'conversion tracking' and the plugin will measure how much turn-over is coming from your marketing campaigns. The plugin uses both session- and cookie-conversions to make sure all sales are tracked.
46
 
53
  = Category / taxonomy mapping =
54
  Some marketing channels require you to map your categories to theirs (such as Google Shopping). This plugin enables you to exactly do that. Not only does it support 1-to-1 category mapping but you can also map subsets of products on a channel-category based on product names.
55
 
56
+ = Google Shopping =
57
+ Our plugin offers added and advanced features for creating the best possible product feed for Google Shopping. Feeds created by our plugin have a high approval rate on products in Google's Merchant center. Also, because of a WooCommerce bug in the structured data of variable products all of these products would normally be disapproved in Google's merchant center. Our plugin fixes this bug and enables you to advertise on all of your products in Google Shopping.
58
+
59
  = Google Analytics support =
60
  This plugin enables you to add and configure Google Analytics UTM tracking-codes to your product URL’s so you can measure the effectiveness of your marketing channels in Google Analytics.
61
 
79
  * Unlimited number of product feeds
80
  * > 100 pre-configured product feed channel-templates for ~ 200 countries;
81
  * Create custom product feeds;
82
+ * XML, CSV, TSV and TXT formats;
83
  * Tracks conversions and sales;
84
  * Intuitive interface;
85
  * Supports product variations / variables;
86
  * Scheduled product feed refreshes: daily, twice-daily or every hour;
87
+ * Supported file formats: XML, CSV,TXT and TSV;
88
  * Supports shipping zones, shipping classes and shipping cost
89
  * Filters and rules: set product filter and rules so only the right products end up in the product feed;
90
  * Category / Taxonomy mapping: map your categories to those of other channels, such as Google Shopping;
95
  * Supports the official Facebook for WooCommerce plugin (SKU_ID parameter)
96
  * Supports Yoasts primary category feature
97
  * Supports Yith brand attributes
98
+ * Supports WooCommerce Dynamic Pricing & Discounts from RightPress
99
 
100
  === Channels ===
101
  * Custom feeds
102
  * Google Shopping
103
  * Google DRM / Dynamic remarketing
104
+ * Google Merchant Promotions feed
105
  * Facebook Dynamic Ad’s / remarketing
106
  * Bing Shopping
107
  * <a href="https://yandex.com/support/market-tech-requirements/index.html" target="_blank">Yandex</a>
114
  * <a href="https://www.comparer.be" target="_blank">Comparer.be</a>
115
  * Kieskeurig.nl
116
  * Kieskeurig.be
117
+ * <a href="https://www.beslist.nl" target="_blank" rel="nofollow">Beslist.nl</a>
118
+ * <a href="https://www.beslist.be" target="_blank" rel="nofollow">Beslist.be</a>
119
  * Bol.com
120
  * Stylight
121
  * Incurvy
122
+ * <a href="https://www.kijiji.it" target="_blank">Kijiji Italy</a>
123
  * Kelkoo
124
  * <a href="https://www.zbozi.cz" target="_blank">Zbozi.cz</a>
125
  * Shopalike
171
  * Trovaprezzi
172
  * Tweakers.nl
173
  * Kleding.nl
174
+ * ManoMano.co.uk
175
 
176
  == Installation ==
177
 
249
 
250
  === Changelog ===
251
 
252
+ = 3.0.0 (2018-05-16) =
253
+ * Bug fix for include_only filters
254
+
255
+ = 2.9.9 (2018-05-16) =
256
+ * Bug fix for filters on strings
257
+
258
+ = 2.9.8 (2018-05-16) =
259
+ * Added an extra template field tax for the Skroutz feeds
260
+
261
+ = 2.9.7 (2018-05-16) =
262
+ * Add a filter option to 'include only' on 'is not equal to' string values
263
+
264
+ = 2.9.6 (2018-05-16) =
265
+ * Added some more cleaning-up upon deinstallation of plugin
266
+
267
+ = 2.9.5 (2018-05-15) =
268
+ * Added some clean-up functionalities: when the plugin gets disabled it removed the hooks created to automatically refresh the feed and check the license. When the plugin is deleted the entire product feed configuration is deleted.
269
+
270
+ = 2.9.4 (2018-05-14) =
271
+ * Solved a stack trace error that in some cases stopped the automatic update process of product feeds
272
+
273
+ = 2.9.3 (2018-05-13) =
274
+ * Fixed minor count error
275
+
276
+ = 2.9.2 (2018-05-11) =
277
+ * Fixed the preg_match errors upon generation of the feed
278
+
279
+ = 2.9.1 (2018-05-11) =
280
+ * Added the possibility to map a channel price to your front-end price (price inserted excl. VAT, shown including VAT)
281
+ * Fixed a minor shipping price big
282
+
283
+ = 2.9.0 (2018-05-11) =
284
+ * Fixed a missing tab in a drop-down when fileformat TSV was chosen
285
+ * Fixed a bug with attribute mappings not being saved correctly
286
+ * Renamed a ManoMano template field
287
+
288
+ = 2.8.5 (2018-05-08) =
289
+ * Major update to the category mapping feature. The mapping is no longer restricted to ~ 300 categories, you can map as many categories as needed from now on. We managed to bypass some PHP restrictions in this update.
290
+
291
+ = 2.8.4 (2018-05-07) =
292
+ * We hear you, not being able to remove the license notification is a pain in the *** ;-) Our apologies for this bug, just like all our other notifications you can now disable the notification and it won't ever show again.
293
+
294
+ = 2.8.3 (2018-05-07) =
295
+ * Doubled the speed for creation of product feeds for shops that contain over 50.000 products
296
+
297
+ = 2.8.2 (2018-05-04) =
298
+ * Added the ManoMano.co.uk marketplace template
299
+
300
+ = 2.8.1 (2018-05-04) =
301
+ * Fixed an issue with the condition attribute. The default value of condition is, as of now, 'New' so this value will never be empty
302
+ * Fixed a minor issue with regards to the identifier_exists field for Google Shopping. The plugin calculates itself if the value needs to be no or yes completly ignoring static values entered by users. This has now been solved
303
+ * Did some restyling of the admin screens
304
+
305
+ = 2.8.0 (2018-05-03) =
306
+ * Fixed a bug with the product exclude option for variation products
307
+
308
+ = 2.7.9 (2018-05-03) =
309
+ * Fixed bug for WooCommerce Dynamic Pricing & Discounts from RightPress
310
+
311
+ = 2.7.8 (2018-05-02) =
312
+ * Update for Elite users: set a parent brand for all your variants so you do not have to fill in the brand for all variant products. The optimized title now overwrites the normal product title and when the optimized title is left blank the plugin falls back to using the normal product title. Like this you do not have to fill in an optimized title for every product.
313
+
314
+ = 2.7.7 (2018-05-02) =
315
+ * Fixed the double concatenation of (default) attribute values to variant product names
316
+
317
+ = 2.7.6 (2018-05-01) =
318
+ * Added support for WooCommerce Dynamic Pricing & Discounts from RightPress
319
+
320
+ = 2.7.5 (2018-05-01) =
321
+ * Fixed a minor custom attributes bug
322
+
323
+ = 2.7.4 (2018-05-01) =
324
+ * Added support for WooCommerce Dynamic Pricing & Discounts from RightPress
325
+
326
+ = 2.7.3 (2018-05-01) =
327
+ * Solved a bug that concatenated attributes value to the product name multiple times (thanks for reporting @jjuul)
328
+
329
+ = 2.7.2 (2018-04-30) =
330
+ * Added the unit pricing measure and unit pricing base measure fields for Google Shopping feeds
331
+
332
+ = 2.7.1 (2018-04-30) =
333
+ * Removed duplicate triggering of cron_hook
334
+
335
+ = 2.7.0 (2018-04-30) =
336
+ * Fixed a bug with regards to the unit_pricing_base_measure field for Google Shopping
337
+
338
+ = 2.6.9 (2018-04-29) =
339
+ * Fixed a JSON structured data bug
340
+
341
+ = 2.6.8 (2018-04-29) =
342
+ * Added UTF8 encoding to the Google Shopping XML product feeds (thanks @exentric and tkellmen!)
343
+
344
+ = 2.6.7 (2018-04-27) =
345
+ * Removed some notifications
346
+
347
+ = 2.6.6 (2018-04-26) =
348
+ * Improved housekeeping cleanup when an user deactivates the plugin
349
+
350
+ = 2.6.5 (2018-04-26) =
351
+ * Added a backup cron hook for kickstarting product feeds that got stuck during processing
352
+ * Improvement license validation check, based on domain
353
+
354
+ = 2.6.4 (2018-04-25) =
355
+ * Improved notification texts and enhanced license validation check
356
+
357
+ = 2.6.3 (2018-04-25) =
358
+ * Added the Google Merchant Promotions Feed template
359
+
360
+ = 2.6.2 (2018-04-23) =
361
+ * Improved performance of the plugin and changed order of file format selector/drop-down
362
+
363
+ = 2.6.1 (2018-04-13) =
364
+ * Fixed another JSON bug
365
+
366
+ = 2.6.0 (2018-04-12) =
367
+ * Fixed a structured data JSON bug (thanks for reporting @gregbast1994)
368
+
369
+ = 2.5.9 (2018-04-12) =
370
+ * Added a 'no refresh' interval option for users who do not need the feeds to be refreshed automatically
371
+ * For WooCommerce stores with thousands of products the configuration of a product feed itself sometimes became really slow. This issues has been fixed
372
+
373
+ = 2.5.8 (2018-04-11) =
374
+ * Fixed minor bug in structured data JSON markup
375
+
376
+ = 2.5.7 (2018-04-10) =
377
+ * Added helptexts for our new feature that adds the custom attributes such as GTIN, MPN, EAN, Brand, Condition, etc
378
+
379
+ = 2.5.6 (2018-04-09) =
380
+ * Added support for the following structured data fields on your product pages: itemCondition and availability. This will result in less disapproved items in your Google Merchant Center;
381
+ * Fixed a structured data bug for the price field (occured for variable products that existed out of two or more attributes);
382
+ * Fixed a fatal PHP error for a missing exclude filter;
383
+ * Added the Elite license validation module (beta testing phase)
384
+
385
+ = 2.5.5 (2018-04-05) =
386
+ * We have added a checkbox on both the simple and variable edit pages that you can enable if you want to exclude a certain product from product feeds. This was already possible making filters however we found this to be a more user-friendly solution.
387
+
388
+ = 2.5.4 (2018-04-04) =
389
+ * Big release: we have added an option for you to enable in the plugin settings that will add important fields / attributes for your products which you need to meet Google's requirements. Enabling this option will give you these extra fields / attributes: Brand, GTIN, MPN, UPC, EAN, Product condition (New, Refurbished, Used) and an Optimised title field. These fields / attributes can than be used for mapping them to the correct Google Shopping fields.
390
+ * The added 'Product condition' field value will also be used on your product page JSON's so your products will not be disapproved in Google's Merchant Center.
391
+
392
+ = 2.5.3 (2018-30-03) =
393
+ * Fixed the empty item tags in Google Shopping feeds caused by filtering
394
+
395
+ = 2.5.2 (2018-30-03) =
396
+ * Added JSON itemCondition to the product page so products in Google Shopping are not getting disapproved because of this
397
+
398
+ = 2.5.1 (2018-30-03) =
399
+ * Fixed a filter and rule bug where some of the filters and rule configurations got lost
400
+ * Fixed a filter bug on numeric value (for example filters on price)
401
+ * Added helptext for users pointing to instructions on how to set filters
402
+
403
+ = 2.5.0 (2018-29-03) =
404
+ * Solved a bug calling a non existing function
405
+
406
+ = 2.4.9 (2018-29-03) =
407
+ * Rollback trying to revert a bug
408
+
409
+ = 2.4.2 (2018-28-03) =
410
+ * When the Yoast Premium plugin was installed but not active and a product sat in multiple categories the g:google_product_category field was left empty in the product feed. This bug has now been solved.
411
+
412
+ = 2.4.1 (2018-28-03) =
413
+ * Reverted to an older version as the plugin caused processing of big feeds to get stuck
414
+
415
+ = 2.3.6 (2018-23-03) =
416
+ * Added the Sale price effective date attribute so it can be used in Google Shopping feeds
417
+
418
+ = 2.3.5 (2018-23-03) =
419
+ * Prevented custom attributes that have no value from showing up in the product feeds as empty nodes
420
+
421
+ = 2.3.4 (2018-23-03) =
422
+ * Added CDATA brackets for the title, description and short_description attributes to prevent XML formatting errors
423
+
424
+ = 2.3.3 (2018-23-03) =
425
+ * Because of PHP limitations it was not possible to map more than 165 categories to Google Shopping categories. We have now been able to increase that number to 330 categories.
426
+
427
+ = 2.3.2 (2018-22-03) =
428
+ * Custom attributes that are being added by external plugins that begin with a underscore in its naming now also can be used in the plugin
429
+
430
+ = 2.3.1 (2018-22-03) =
431
+ * Solved a bug in the field mapping page where numeric product attribute names caused mapping issues
432
+
433
+ = 2.3.0 (2018-21-03) =
434
+ * Removed non-line-break characters from the product feeds in the description and short_description attributes
435
+
436
+ = 2.2.9 (2018-21-03) =
437
+ * Fixed some UTF-8 decoding issues causing XML formatting errors in Google's Merchant Center
438
+
439
+ = 2.2.8 (2018-21-03) =
440
+ * Added HTML decode for the description and short_description attributes so it shows the characters in the product feed as it should
441
+
442
+ = 2.2.7 (2018-20-03) =
443
+ * It is now possible to map the same custom attribute for both single and variable products
444
+ * Improved speed of creating product feeds
445
+ * Fixed a bug where filters removed all product data but left an empty category XML node in the feed
446
+
447
+ = 2.2.6 (2018-17-03) =
448
+ * Changed the XML header for Zbozi.cz product feeds
449
+
450
+ = 2.2.5 (2018-17-03) =
451
+ * Added TSV (tab-seperated) support for all channels.
452
+ * Added Miinto.nl template
453
+
454
+ = 2.2.4 (2018-16-03) =
455
+ * When product stock management was active WooCommerce returns a product as being 'Out of stock even when the stock quantity is > 0. We think this makes no sense so we made changes to the plugin. When stock management is active on product level and the stock quantity > 0 we will put the availability value on "in stock" as of this new release.
456
+
457
+ = 2.2.3 (2018-15-03) =
458
+ * We have made some functional changes to the Google Shopping category mapping option. Whereas in older versions of the plugin the category attribute was overwritten a potential Google category ID coming from a Google category mapping this can now be prevented with selecting the 'Category (not used for mapping)' option in the drop-downs on the attribute mapping page.
459
+
460
+ = 2.2.2 (2018-14-03) =
461
+ * Added the attribute publication date as one of the attributes that can be added to product feeds, such as Kijiji Italy.
462
+
463
+ = 2.2.1 (2018-11-03) =
464
+ * Fixed some broken CSS
465
+ * Added explanations about the WooCommerce Structured Data mark-up bug
466
+
467
+ = 2.2.0 (2018-09-03) =
468
+ * CSS bullet lists broke in some browsers resulting in an ugly plugin interface. This has now been fixed..
469
+
470
+ = 2.1.9 (2018-09-03) =
471
+ * Added some extra picture fields to the Kijiji Italy template
472
+
473
+ = 2.1.8 (2018-08-03) =
474
+ * Fixed a bug in the rules and filers (some rules got lost with the previous update of the plugin)
475
+
476
+ = 2.1.7 (2018-07-03) =
477
+ * Rules that removed products from your WooCommerce Google Shopping product feed did not remove the <item/> XML closure tag. Although this is not wrong XML and did not cause issues with submitting the feed to Google's Merchant Center we did clean it up.
478
+
479
+ = 2.1.6 (2018-07-03) =
480
+ * Added Kijiji Italy template
481
+
482
+ = 2.1.5 (2018-06-03) =
483
+ * Improved error notifications
484
+ * Added review request notification
485
+
486
+ = 2.1.4 (2018-25-02) =
487
+ * Made some changes to the 'grant access' feature of the plugin
488
+
489
+ = 2.1.3 (2018-24-02) =
490
+ * Doing some housekeeping: cleaning up files and cron jobs after deactivation of the plugin
491
+ * Removed some error messages
492
+
493
+ = 2.1.2 (2018-24-02) =
494
+ * Because of a bug in WooCommerce variable products will get disapproved in Google's Merchant Center. WooCommerce adds the price of the cheapest variable product in the structured data for all variations of a product. Because of this there will be a mismatch between the product price you provide to Google in your Google Shopping product feed and the structured data price on the product landingpage. Google will therefor disapprove the product in its merchant center. You won't be able to advertise on that product in your Google Shopping campaign. The plugin now contains and option to fix the structured data on variable product pages by adding the correct variable product price in the JSON-LD structured data so Google will approve the variable products you submitted. Prices you provide in your Google Shopping product feed for variable products will now match the actual prices of those products on yor product pages.
495
+
496
+ = 2.1.1 (2018-14-02) =
497
+ * Fixed an issue with the g:identifier_exists attribute for Google Shopping product feed
498
+ * Added helptexts to the attribute mapping page
499
+ * Now allowing underscores in XML namespaces for custom feed fields
500
+
501
+ = 2.1.0 (2018-09-02) =
502
+ * Cleaned-up the list of attributes to map and set filter and rules on making it easier to map fields and set filter or rules.
503
+
504
+ = 2.0.9 (2018-07-02) =
505
+ * Added support for filtering on empty fields
506
+
507
+ = 2.0.8 (2018-06-02) =
508
+ * Added support for custom fields that are being added by other plugins
509
+
510
+ = 2.0.7 (2018-04-02) =
511
+ * Added conversion data to the debug.log in preparation for filtering on product conversions
512
+
513
+ = 2.0.6 (2018-02-02) =
514
+ * Plugin now automatically puts currency prefixes in place for Google Shopping and Facebook feeds as this is required by Google Shopping. As a result your Google Shopping product feeds will now contain a default currency so you do not have to add the currency yourselves in Google's merchant center
515
+ * Minor changes for Beslist.nl and Beslist.be templates
516
+
517
+ = 2.0.5 (2018-30-01) =
518
+ * Fixed minor bug: questionmark was appended to the link attribute when tracking was disabled for simple products. This has now been solved.
519
+
520
+ = 2.0.4 (2018-30-01) =
521
+ * Significantly improved speed of processing product feeds
522
+ * Added templates for Beslist.nl and Beslist.be
523
+
524
+ = 2.0.3 (2018-23-01) =
525
+ * Fixed some styling and text issues.
526
+
527
+ = 2.0.2 (2018-21-01) =
528
+ * Solved major bugs with Product and Dynamic attribute mappings
529
+
530
+ = 2.0.1 (2018-19-01) =
531
+ * Solved a bug that was introduced with the last release. The g:id field for Google Shopping product feeds accidently got stripped. This bug has been solved now.
532
+
533
  = 2.0.0 (2018-18-01) =
534
  * Added a new field "Category path". This field shows the so-called breadcrumb and can be used for your productfeed (needed for Prisjakt)
535
 
549
  * Fixed a bug: additional gallery images are now also shown in Custom XML feeds
550
 
551
  = 1.9.4 (2018-05-01) =
552
+ * Fixed a bug: additional gallery images are now also shown in XML and Google Shopping product feed
553
 
554
  = 1.9.3 (2018-05-01) =
555
  * Added the possibility map products on Google Shopping categories based on advanced rules. You can now map your products to Google Shopping categories not only based on the product category but on any product attribute.
834
 
835
  == Upgrade Notice ==
836
 
837
+ = 3.0.0 =
838
+ Bug fix for include_only filters
839
+
840
+ = 2.9.9 =
841
+ Bug fix for filters on strings
842
+
843
+ = 2.9.8 =
844
+ Added an extra template field tax for the Skroutz feeds
845
+
846
+ = 2.9.7 =
847
+ Add a filter option to 'include only' on 'is not equal to' string values
848
+
849
+ = 2.9.6 =
850
+ Added some more cleaning-up upon deinstallation of plugin
851
+
852
+ = 2.9.5 =
853
+ Added some clean-up functionalities: when the plugin gets disabled it removed the hooks created to automatically refresh the feed and check the license. When the plugin is deleted the entire product feed c
854
+ onfiguration is deleted.
855
+
856
+ = 2.9.4 =
857
+ Solved a stack trace error that in some cases stopped the automatic update process of product feeds
858
+
859
+ = 2.9.3 =
860
+ Fixed minor count error
861
+
862
+ = 2.9.2 =
863
+ Fixed the preg_match errors upon generation of the feed
864
+
865
+ = 2.9.1 =
866
+ Added the possibility to map a channel price to your front-end price (price inserted excl. VAT, shown including VAT)
867
+ Fixed a minor shipping price big
868
+
869
+ = 2.9.0 =
870
+ Fixed a missing tab in a drop-down when fileformat TSV was chosen
871
+ Renamed a ManoMano template field
872
+
873
+ = 2.8.5 =
874
+ Major update to the category mapping feature. The mapping is no longer restricted to ~ 300 categories, you can map as many categories as needed from now on. We managed to bypass some PHP restrictions in this update.
875
+
876
+ = 2.8.4 =
877
+ License notification can now be disabled
878
+
879
+ = 2.8.3 =
880
+ Doubled the speed for creation of product feeds for shops that contain over 50.000 products
881
+
882
+ = 2.8.2 =
883
+ Added the ManoMano.co.uk marketplace template
884
+
885
+ = 2.8.1 =
886
+ Fixed a minor issue with the condition attribute. The default value of condition is, as of now, 'New' so this value will never be empty
887
+ Fixed a minor issue with regards to the identifier_exists field for Google Shopping. The plugin calculates itself if the value needs to be no or yes completly ignoring static values entered by users. This has now been solved
888
+ Did some restyling of the admin screens
889
+
890
+ = 2.8.0 =
891
+ Fixed a bug with the product exclude option for variation products
892
+
893
+ = 2.7.9 =
894
+ Fixed bug for WooCommerce Dynamic Pricing & Discounts from RightPress
895
+
896
+ = 2.7.8 =
897
+ Parent brand used for variations and optimized title using normal product title as fallback
898
+
899
+ = 2.7.7 =
900
+ Fixed the double concatenation of (default) attribute values to variant product names
901
+
902
+ = 2.7.6 =
903
+ Added support for WooCommerce Dynamic Pricing & Discounts from RightPress
904
+
905
+ = 2.7.5 =
906
+ Fixed a minor custom attributes bug
907
+
908
+ = 2.7.4 =
909
+ Added support for WooCommerce Dynamic Pricing & Discounts from RightPress
910
+
911
+ = 2.7.3 =
912
+ Solved a bug that concatenated attributes value to the product name multiple times (thanks for reporting @jjuul)
913
+
914
+ = 2.7.2 =
915
+ Added the unit pricing measure and unit pricing base measure fields for Google Shopping feeds
916
+
917
+ = 2.7.1 =
918
+ Removed duplicate triggering of cron_hook
919
+
920
+ = 2.7.0 =
921
+ Fixed a bug with regards to the unit_pricing_base_measure field for Google Shopping
922
+
923
+ = 2.6.9 =
924
+ Fixed a JSON structured data bug
925
+
926
+ = 2.6.8 =
927
+ Added UTF8 encoding to the Google Shopping XML product feeds (thanks @exentric and tkellmen!)
928
+
929
+ = 2.6.7 =
930
+ Removed some notifications
931
+
932
+ = 2.6.6 =
933
+ Improved housekeeping cleanup when an user deactivates the plugin
934
+
935
+ = 2.6.5 =
936
+ Added a backup cron hook for kickstarting product feeds that got stuck during processing
937
+ Improvement license validation check, based on domain
938
+
939
+ = 2.6.4 =
940
+ Improved notification texts and enhanced license validation check
941
+
942
+ = 2.6.3 =
943
+ Added the Google Merchant Promotions Feed template
944
+
945
+ = 2.6.2 =
946
+ Improved performance of the plugin and changed order of file format selector/drop-down
947
+
948
+ = 2.6.1 =
949
+ Fixed another JSON bug
950
+
951
+ = 2.6.0 =
952
+ Fixed a structured data JSON bug (thanks for reporting @gregbast1994)
953
+
954
+ = 2.5.9 =
955
+ Added a 'no refresh' interval option for users who do not need the feeds to be refreshed automatically
956
+ For WooCommerce stores with thousands of products the configuration of a product feed itself sometimes became really slow. This issues has been fixed
957
+
958
+ = 2.5.8 =
959
+ Fixed minor bug in structured data JSON markup
960
+
961
+ = 2.5.7 =
962
+ Added helptexts for our new feature that adds the custom attributes such as GTIN, MPN, EAN, Brand, Condition, etc
963
+
964
+ = 2.5.6 =
965
+ Added support for the following structured data fields on your product pages: itemCondition and availability. This will result in less disapproved items in your Google Merchant Center;
966
+ Fixed a structured data bug for the price field (occured for variable products that existed out of two or more attributes);
967
+ Fixed a fatal PHP error for a missing exclude filter;
968
+ Added the Elite license validation module (beta testing phase)
969
+
970
+ = 2.5.5 =
971
+ We have added a checkbox on both the simple and variable edit pages that you can enable if you want to exclude a certain product from product feeds. This was already possible making filters however we found this to be a more user-friendly solution.
972
+
973
+ = 2.5.4 =
974
+ Big release: we have added an option for you to enable in the plugin settings that will add important fields / attributes for your products which you need to meet Google's requirements. Enabling this option will give you these extra fields / attributes: Brand, GTIN, MPN, UPC, EAN, Product condition (New, Refurbished, Used) and an Optimised title field. These fields / attributes can than be used for mapping them to the correct Google Shopping fields.
975
+ The added 'Product condition' field value will also be used on your product page JSON's so your products will not be disapproved in Google's Merchant Center.
976
+
977
+ = 2.5.3 =
978
+ Fixed the empty item tags in Google Shopping feeds caused by filtering
979
+
980
+ = 2.5.2 =
981
+ Added JSON itemCondition to the product page so products in Google Shopping are not getting disapproved because of this
982
+
983
+ = 2.5.1 =
984
+ Fixed a filter and rule bug where some of the filters and rule configurations got lost
985
+ Fixed a filter bug on numeric value (for example filters on price)
986
+ Added helptext for users pointing to instructions on how to set filters
987
+
988
+ = 2.5.0 =
989
+ Solved a bug calling an undefined function
990
+
991
+ = 2.4.9 =
992
+ Rollback trying to revert a bug
993
+
994
+ = 2.4.2 =
995
+ When the Yoast Premium plugin was installed but inactive and a product sat in multiple categories the g:google_product_category was left empty in product feeds. This has now been solved.
996
+
997
+ = 2.4.1 =
998
+ Reverted to an older version as the plugin caused processing of big feeds to get stuck
999
+
1000
+ = 2.3.6 =
1001
+ Added the Sale price effective date attribute so it can be used in Google Shopping feeds
1002
+
1003
+ = 2.3.5 =
1004
+ Prevented custom attributes that have no value from showing up in the product feeds as empty nodes
1005
+
1006
+ = 2.3.4 =
1007
+ Added CDATA brackets for the title, description and short_description attributes to prevent XML formatting errors
1008
+
1009
+ = 2.3.3 =
1010
+ Because of PHP limitations it was not possible to map more than 165 categories to Google Shopping categories. We have now been able to increase that number to 330 categories.
1011
+
1012
+ = 2.3.2 =
1013
+ Custom attributes that are being added by external plugins that begin with a underscore in its naming now also can be used in the plugin
1014
+
1015
+ = 2.3.1 =
1016
+ Solved a bug in the field mapping page where numeric product attribute names caused mapping issues
1017
+
1018
+ = 2.3.0 =
1019
+ Removed non-line-break characters from the product feeds in the description and short_description attributes
1020
+
1021
+ = 2.2.9 =
1022
+ Fixed some UTF-8 decoding issues causing XML formatting errors in Google's Merchant Center
1023
+
1024
+ = 2.2.8 =
1025
+ Added HTML decode for the description and short_description attributes so it shows the characters in the product feed as it should
1026
+
1027
+ = 2.2.7 =
1028
+ It is now possible to map the same custom attribute for both single and variable products
1029
+ Improved speed of creating product feeds
1030
+ Fixed a bug where filters removed all product data but left an empty category XML node in the feed
1031
+
1032
+ = 2.2.6 =
1033
+ Changed the XML header for Zbozi.cz product feeds
1034
+
1035
+ = 2.2.5 =
1036
+ Added TSV (tab-seperated) support for all channels.
1037
+ Added Miinto.nl template
1038
+
1039
+ = 2.2.4 =
1040
+ When product stock management was active WooCommerce returns a product as being 'Out of stock even when the stock quantity is > 0. We think this makes no sense so we made chan
1041
+ ges to the plugin. When stock management is active on product level and the stock quantity > 0 we will put the availability value on "in stock" as of this new release.
1042
+
1043
+ = 2.2.3 =
1044
+ Added a Category (not used for mapping) attribute in the drop-downs
1045
+
1046
+ = 2.2.2 =
1047
+ Added the attribute publication date as one of the attributes that can be added to product feeds, such as Kijiji Italy.
1048
+
1049
+ = 2.2.1 =
1050
+ Fixed some broken CSS
1051
+ Added explanations about the WooCommerce Structured Data mark-up bug
1052
+
1053
+ = 2.2.0 =
1054
+ CSS bullet lists broke in some browsers resulting in an ugly plugin interface. This has now been fixed..
1055
+
1056
+ = 2.1.9 =
1057
+ Added some extra picture fields to the Kijiji Italy template
1058
+
1059
+ = 2.1.8 =
1060
+ Fixed a bug in the rules and filers (some rules got lost with the previous update of the plugin)
1061
+
1062
+ = 2.1.7 =
1063
+ Rules that removed products from your WooCommerce Google Shopping product feed did not remove the <item/> XML closure tag. Although this is not wrong XML and did not cause issues with submitting the feed to Google's Merchant Center we did clean it up.
1064
+
1065
+ = 2.1.6 =
1066
+ Added Kijiji Italy template
1067
+
1068
+ = 2.1.5 =
1069
+ Improved error notifications
1070
+ Added review request notification
1071
+
1072
+ = 2.1.4 =
1073
+ Made some changes to the 'grant access' feature of the plugin
1074
+
1075
+ = 2.1.3 =
1076
+ Doing some housekeeping: cleaning up files and cron jobs after deactivation of the plugin
1077
+ Removed error messages
1078
+
1079
+ = 2.1.2 =
1080
+ Because of a bug in WooCommerce variable products will get disapproved in Google's Merchant Center. WooCommerce adds the price of the cheapest variable product in the structured data for all variations of a product. Because of this there will be a mismatch between the product price you provide to Google in your Google Shopping product feed and the structured data price on the product landingpage. Google will therefor disapprove the product in its merchant center. You won't be able to advertise on that product in your Google Shopping campaign. The plugin now contains and option to fix the structured data on variable product pages by adding the correct variable product price in the JSON-LD structured data so Google will approve the variable products you submitted.
1081
+
1082
+ = 2.1.1 =
1083
+ Fixed an issue with the g:identifier_exists attribute
1084
+ Added helptexts to the attribute mapping page
1085
+ Now allowing underscores in XML namespaces for custom feed fields
1086
+
1087
+ = 2.1.0 =
1088
+ Cleaned-up the list of attributes to map and set filter and rules on making it easier to map fields and set filter or rules.
1089
+
1090
+ = 2.0.9 =
1091
+ Added support for filtering on empty fields
1092
+
1093
+ = 2.0.8 =
1094
+ Added support for custom fields that are being added by other plugins
1095
+
1096
+ = 2.0.7 =
1097
+ Added conversion data to the debug.log in preparation for filtering on product conversions
1098
+
1099
+ = 2.0.6 =
1100
+ Plugin now automatically puts currency prefixes in place for Google Shopping and Facebook feeds
1101
+ Minor changes for Beslist templates
1102
+
1103
+ = 2.0.5 =
1104
+ Fixed minor bug: questionmark was appended to the link attribute when tracking was disabled for simple products. This has now been solved.
1105
+
1106
+ = 2.0.4 =
1107
+ Significantly improved speed of processing product feeds
1108
+ Added templates for Beslist.nl and Beslist.be
1109
+
1110
+ = 2.0.3 =
1111
+ Fixed some styling and text issues.
1112
+
1113
+ = 2.0.2 =
1114
+ Solved major bugs with Product and Dynamic attribute mappings
1115
+
1116
+ = 2.0.1 =
1117
+ Solved a bug that was introduced with the last release. The g:id field for Google Shopping products feed accidently got stripped. This bug has been solved now.
1118
+
1119
  = 2.0.0 =
1120
  Added the category path field which can be used to show the category path or so called breadcrumn in your product feeds
1121
 
woocommerce-sea.php CHANGED
@@ -1,15 +1,19 @@
1
  <?php
2
  /**
3
  * Plugin Name: WooCommerce Product Feed PRO
4
- * Version: 2.0.0
 
5
  * Description: Configure and maintain your WooCommerce product feeds for Google Shopping, Facebook, Remarketing, Bing, Yandex, Comparison shopping websites and over a 100 channels more.
6
  * Author: AdTribes.io
 
7
  * Author URI: https://www.adtribes.io
8
- * Developer: Joris Verwater
9
  * License: GPL3
10
  * License URI: https://www.gnu.org/licenses/gpl-3.0.html
11
  * Text Domain: wporg
12
  * Domain Path: /languages
 
 
13
  */
14
 
15
  /**
@@ -41,7 +45,7 @@ if (!defined('ABSPATH')) {
41
  /**
42
  * Plugin versionnumber, please do not override
43
  */
44
- define( 'WOOCOMMERCESEA_PLUGIN_VERSION', '2.0.0' );
45
  define( 'WOOCOMMERCESEA_PLUGIN_NAME', 'woocommerce-product-feed-pro' );
46
 
47
  if ( ! defined( 'WOOCOMMERCESEA_FILE' ) ) {
@@ -79,6 +83,7 @@ function woosea_scripts($hook) {
79
  // Enqueue Jquery
80
  wp_enqueue_script('jquery');
81
  wp_enqueue_script('jquery-ui-dialog');
 
82
 
83
  // Bootstrap typeahead
84
  wp_register_script( 'typeahead-js', plugin_dir_url( __FILE__ ) . 'js/typeahead.js', '',WOOCOMMERCESEA_PLUGIN_VERSION, true );
@@ -108,11 +113,9 @@ function woosea_scripts($hook) {
108
  wp_register_script( 'woosea_manage-js', plugin_dir_url( __FILE__ ) . 'js/woosea_manage.js', '',WOOCOMMERCESEA_PLUGIN_VERSION, true );
109
  wp_enqueue_script( 'woosea_manage-js' );
110
 
111
- // JS for checking license, only check on plugin page when plugin is (re)installed
112
- if ($hook == 'plugins.php'){
113
- wp_register_script( 'woosea_adtribes-js', plugin_dir_url( __FILE__ ) . 'js/woosea_license.js', '',WOOCOMMERCESEA_PLUGIN_VERSION, true );
114
- wp_enqueue_script( 'woosea_adtribes-js' );
115
- }
116
  }
117
  add_action( 'admin_enqueue_scripts' , 'woosea_scripts' );
118
 
@@ -126,6 +129,15 @@ require plugin_dir_path(__FILE__) . 'classes/class-admin-notifications.php';
126
  require plugin_dir_path(__FILE__) . 'classes/class-update-channel.php';
127
  require plugin_dir_path(__FILE__) . 'classes/class-attributes.php';
128
 
 
 
 
 
 
 
 
 
 
129
  /**
130
  * Hook and function that will run during plugin deactivation.
131
  */
@@ -144,6 +156,50 @@ function activate_woosea_feed(){
144
  }
145
  register_activation_hook(__FILE__, 'activate_woosea_feed');
146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
  /**
148
  * Create a seperate MySql table for saving conversion information
149
  */
@@ -214,6 +270,12 @@ add_action( 'woocommerce_thankyou', 'woosea_inject_ajax' );
214
  */
215
  add_action( 'woosea_cron_hook', 'woosea_create_all_feeds'); // create a cron hook
216
 
 
 
 
 
 
 
217
  /**
218
  * Add WooCommerce SEA plugin to Menu
219
  */
@@ -221,7 +283,8 @@ function woosea_menu_addition(){
221
  add_menu_page(__('WooCommerce Product Feed PRO', 'woosea-feed'), __('Product Feed Pro', 'woosea-feed'), 'manage_options', __FILE__, 'woosea_generate_pages', 'dashicons-chart-bar',99);
222
  add_submenu_page(__FILE__, __('Feed configuration', 'woosea-feed'), __('Create feed', 'woosea-feed'), 'manage_options', __FILE__, 'woosea_generate_pages');
223
  add_submenu_page(__FILE__, __('Manage feeds', 'woosea-feed'), __('Manage feeds', 'woosea-feed'), 'manage_options', 'woosea_manage_feed', 'woosea_manage_feed');
224
- add_submenu_page(__FILE__, __('Plugin settings', 'woosea-feed'), __('Plugin settings', 'woosea-feed'), 'manage_options', 'woosea_manage_settings', 'woosea_manage_settings');
 
225
  }
226
 
227
  /**
@@ -248,6 +311,324 @@ function woosea_ajax() {
248
  }
249
  add_action( 'wp_ajax_woosea_ajax', 'woosea_ajax' );
250
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  /**
252
  * Get the shipping zone countries and ID's
253
  */
@@ -416,6 +797,479 @@ function woosea_project_status() {
416
  }
417
  add_action( 'wp_ajax_woosea_project_status', 'woosea_project_status' );
418
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
419
  /**
420
  * Returns the user ID of the user which is used as the
421
  * login for AdTribes support. The user is created here if it doesn't
@@ -433,8 +1287,10 @@ function woosea_create_support_user() {
433
  if($status == "off"){
434
  $user_id = $user->ID;
435
  $del_user = wp_delete_user($user_id);
 
436
  } else {
437
  $user_id = $user->ID;
 
438
  }
439
  } else {
440
  $user_pass = wp_generate_password( 12 );
@@ -449,6 +1305,8 @@ function woosea_create_support_user() {
449
  if ( !( $maybe_user_id instanceof WP_Error ) ) {
450
  $user_id = $maybe_user_id;
451
 
 
 
452
  // notify admin
453
  $user = get_userdata( $user_id );
454
  $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
@@ -462,7 +1320,8 @@ function woosea_create_support_user() {
462
 
463
  // notify AdTribes.io support
464
  $websitehome = wp_specialchars_decode( get_option( 'home' ), ENT_QUOTES );
465
- $websiteadmin = $websitehome."/wp-admin/";
 
466
 
467
  $message = sprintf( __( 'AdTribes.io support user created on %s:', WOOCOMMERCESEA_PLUGIN_NAME ), $blogname ) . "\r\n\r\n";
468
  $message .= sprintf( __( 'Website: %s', WOOCOMMERCESEA_PLUGIN_NAME ), $websitehome ) . "\r\n\r\n";
@@ -470,7 +1329,7 @@ function woosea_create_support_user() {
470
  $message .= sprintf( __( 'Username: %s', WOOCOMMERCESEA_PLUGIN_NAME ), $user->user_login ) . "\r\n\r\n";
471
  $message .= sprintf( __( 'Password: %s', WOOCOMMERCESEA_PLUGIN_NAME ), $user_pass ) . "\r\n\r\n";
472
 
473
- $message .= __( 'The user has the role of a Shop Manager.', WOOCOMMERCESEA_PLUGIN_NAME ) . "\r\n";
474
 
475
  @wp_mail( 'support@adtribes.io', sprintf( __( '[%s] AdTribes.io Support User', WOOCOMMERCESEA_PLUGIN_NAME ), $blogname ), $message);
476
  }
@@ -534,6 +1393,82 @@ function woosea_update_project_history($project_hash){
534
  }
535
  add_action( 'woosea_update_project_stats', 'woosea_update_project_history',1,1 );
536
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
537
  /**
538
  * Get the dropdowns for the fieldmapping page
539
  */
@@ -775,7 +1710,7 @@ function woosea_generate_pages(){
775
  }
776
 
777
  /**
778
- * Check for axtive license, is this a paid version of the plugin?
779
  * This function is called by the cron after 30 seconds. The check only
780
  * needs to be done once and not continuesly so it gets removed.
781
  */
@@ -785,11 +1720,57 @@ function woosea_de_register_license(){
785
  }
786
  add_action( 'woosea_deregister_hook', 'woosea_de_register_license', 99999); // deregister the paid version check after 60 seconds
787
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
788
  /**
789
  * Function used by event scheduling to create feeds
790
  * Feed can automatically be generated every hour, twicedaiy or once a day
791
  */
792
  function woosea_create_all_feeds(){
 
793
  $feed_config = get_option( 'cron_projects' );
794
  $nr_projects = count($feed_config);
795
  $cron_start_date = date("d M Y H:i");
@@ -837,7 +1818,9 @@ function woosea_create_all_feeds(){
837
  } else {
838
  $start_project = woosea_continue_batch($val['project_hash']);
839
  }
840
- unset($start_project);
 
 
841
  } elseif ($val['cron'] == "hourly") {
842
  $batch_project = "batch_project_".$val['project_hash'];
843
  if (!get_option( $batch_project )){
@@ -924,58 +1907,62 @@ function woosea_track_conversion () {
924
 
925
  if($save_conversion == "yes"){
926
  list($project_hash, $plugin, $productId) = explode('|', $adTribesID);
927
- $conversion_timestamp = date("j-n-Y G:i:s");
928
-
929
- // Insert the conversion data into the MySql conversion table
930
- global $wpdb;
931
- $charset_collate = $wpdb->get_charset_collate();
932
- $table_name = $wpdb->prefix . 'adtribes_my_conversions';
933
-
934
- // Get the last order ID
935
- $orderId = get_option( 'last_order_id' );
936
- $inserted_id = 0;
937
- $success = "no";
938
-
939
- // Check if order was not inserted before inserting it.
940
- $orderId_check = $wpdb->get_results("SELECT * FROM $table_name WHERE orderId = '".$orderId."'");
941
- if($wpdb->num_rows == 0){
942
- $wpdb->insert($table_name,
943
- array(
944
- 'conversion_time' => current_time('mysql' , 1),
945
- 'project_hash' => $project_hash,
946
- 'utm_source' => $utm_source,
947
- 'utm_campaign' => $utm_campaign,
948
- 'utm_medium' => $utm_medium,
949
- 'utm_term' => $utm_term,
950
- 'productId' => $productId,
951
- 'orderId' => $orderId
952
- ),
953
- array(
954
- '%s',
955
- '%s',
956
- '%s',
957
- '%s',
958
- '%s',
959
- '%s',
960
- '%d',
961
- '%d'
962
- )
963
- );
964
-
965
- $inserted_id = $wpdb->insert_id;
966
- }
 
 
 
967
 
968
- if($inserted_id > 0){
969
- $success = "yes";
970
- }
971
 
972
- $data = array (
973
- "conversion_saved" => $success,
974
- );
975
 
976
- $data = json_encode($data);
977
- echo $data;
978
- wp_die();
 
979
  }
980
  }
981
  add_action( 'wp_ajax_woosea_track_conversion','woosea_track_conversion');
@@ -1045,6 +2032,15 @@ function woosea_manage_settings(){
1045
  echo $html->get_page();
1046
  }
1047
 
 
 
 
 
 
 
 
 
 
1048
  /**
1049
  * Function for emptying all projects in cron at once
1050
  * Kill-switch for all configured projects, be carefull!
1
  <?php
2
  /**
3
  * Plugin Name: WooCommerce Product Feed PRO
4
+ * Version: 3.0.0
5
+ * Plugin URI: https://www.adtribes.io/support/?utm_source=wpadmin&utm_medium=plugin&utm_campaign=woosea_product_feed_pro
6
  * Description: Configure and maintain your WooCommerce product feeds for Google Shopping, Facebook, Remarketing, Bing, Yandex, Comparison shopping websites and over a 100 channels more.
7
  * Author: AdTribes.io
8
+ * Plugin URI: https://wwww.adtribes.io/pro-vs-elite/
9
  * Author URI: https://www.adtribes.io
10
+ * Developer: Joris Verwater, Eva van Gelooven
11
  * License: GPL3
12
  * License URI: https://www.gnu.org/licenses/gpl-3.0.html
13
  * Text Domain: wporg
14
  * Domain Path: /languages
15
+ * WC requires at least: 3.0
16
+ * WC tested up to: 3.3
17
  */
18
 
19
  /**
45
  /**
46
  * Plugin versionnumber, please do not override
47
  */
48
+ define( 'WOOCOMMERCESEA_PLUGIN_VERSION', '3.0.0' );
49
  define( 'WOOCOMMERCESEA_PLUGIN_NAME', 'woocommerce-product-feed-pro' );
50
 
51
  if ( ! defined( 'WOOCOMMERCESEA_FILE' ) ) {
83
  // Enqueue Jquery
84
  wp_enqueue_script('jquery');
85
  wp_enqueue_script('jquery-ui-dialog');
86
+ wp_enqueue_script('jquery-ui-calender');
87
 
88
  // Bootstrap typeahead
89
  wp_register_script( 'typeahead-js', plugin_dir_url( __FILE__ ) . 'js/typeahead.js', '',WOOCOMMERCESEA_PLUGIN_VERSION, true );
113
  wp_register_script( 'woosea_manage-js', plugin_dir_url( __FILE__ ) . 'js/woosea_manage.js', '',WOOCOMMERCESEA_PLUGIN_VERSION, true );
114
  wp_enqueue_script( 'woosea_manage-js' );
115
 
116
+ // JS for checking license key
117
+ wp_register_script( 'woosea_license-js', plugin_dir_url( __FILE__ ) . 'js/woosea_license.js', '',WOOCOMMERCESEA_PLUGIN_VERSION, true );
118
+ wp_enqueue_script( 'woosea_license-js' );
 
 
119
  }
120
  add_action( 'admin_enqueue_scripts' , 'woosea_scripts' );
121
 
129
  require plugin_dir_path(__FILE__) . 'classes/class-update-channel.php';
130
  require plugin_dir_path(__FILE__) . 'classes/class-attributes.php';
131
 
132
+ /**
133
+ * Hook and function that will run during plugin uninstall.
134
+ */
135
+ function uninstall_woosea_feed(){
136
+ require plugin_dir_path(__FILE__) . 'classes/class-uninstall-cleanup.php';
137
+ WooSEA_Uninstall_Cleanup::uninstall_cleanup();
138
+ }
139
+ register_uninstall_hook(__FILE__, 'uninstall_woosea_feed');
140
+
141
  /**
142
  * Hook and function that will run during plugin deactivation.
143
  */
156
  }
157
  register_activation_hook(__FILE__, 'activate_woosea_feed');
158
 
159
+ /**
160
+ * Request our plugin users to write a review
161
+ **/
162
+ function woosea_request_review(){
163
+ // Only request for a review when:
164
+ // Plugin activation has been > 1 week
165
+ // Active projects > 0
166
+ $cron_projects = get_option( 'cron_projects' );
167
+ if(!empty( $cron_projects )){
168
+ $nr_projects = count($cron_projects);
169
+ $first_activation = get_option ( 'woosea_first_activation' );
170
+ $notification_interaction = get_option( 'woosea_review_interaction' );
171
+ $current_time = time();
172
+ $show_after = 604800; // Show only after one week
173
+ $is_active = $current_time-$first_activation;
174
+
175
+ if(($nr_projects > 0) AND ($is_active > $show_after) AND ($notification_interaction != "yes")){
176
+ echo '<div class="notice notice-info review-notification is-dismissible"><font color="green" style="font-weight:bold";><p>Hey, I noticed you have been using my plugin, WooCommerce Product Feed PRO, for over a week now and have created product feed projects with it - that\'s awesome! Could you please do me a BIG favor and give it a 5-star rating on WordPress? Just to help us spread the word and boost my motivation.<br/>~ Joris Verwater<br><ul><li><span class="ui-icon ui-icon-caret-1-e" style="display: inline-block;"></span><a href="https://wordpress.org/support/plugin/woo-product-feed-pro/reviews?rate=5#new-post" target="_blank" class="dismiss-review-notification">Ok, you deserve it</a></li><li><span class="ui-icon ui-icon-caret-1-e" style="display: inline-block;"></span><a href="#" class="dismiss-review-notification">Nope, maybe later</a></li><li><span class="ui-icon ui-icon-caret-1-e" style="display: inline-block;"></span><a href="#" class="dismiss-review-notification">I already did</a></li></ul></p></font></div>';
177
+ }
178
+ }
179
+ }
180
+ add_action('admin_notices', 'woosea_request_review');
181
+
182
+ /**
183
+ * Request our plugin users to write a review
184
+ **/
185
+ function woosea_license_notice(){
186
+ $license_information = get_option( 'license_information' );
187
+ $license_notification = get_option( 'woosea_license_notification_closed' );
188
+ $screen = get_current_screen();
189
+
190
+ if($screen->id <> 'product-feed-pro_page_woosea_upgrade_elite'){
191
+ if((isset($license_information['notice'])) and ($license_information['notice'] == "true") and ($license_notification <> 'yes')){
192
+ ?>
193
+ <div class="<?php print "$license_information[message_type]"; ?> license_notification">
194
+ <p><?php _e( $license_information['message'], 'sample-text-domain' ); ?></p>
195
+ </div>
196
+ <?php
197
+ }
198
+ }
199
+ }
200
+ add_action('admin_notices', 'woosea_license_notice');
201
+
202
+
203
  /**
204
  * Create a seperate MySql table for saving conversion information
205
  */
270
  */
271
  add_action( 'woosea_cron_hook', 'woosea_create_all_feeds'); // create a cron hook
272
 
273
+
274
+ /**
275
+ * Check if license for Elite version is valid
276
+ */
277
+ add_action( 'woosea_check_license', 'woosea_license_valid'); // check if license is valid
278
+
279
  /**
280
  * Add WooCommerce SEA plugin to Menu
281
  */
283
  add_menu_page(__('WooCommerce Product Feed PRO', 'woosea-feed'), __('Product Feed Pro', 'woosea-feed'), 'manage_options', __FILE__, 'woosea_generate_pages', 'dashicons-chart-bar',99);
284
  add_submenu_page(__FILE__, __('Feed configuration', 'woosea-feed'), __('Create feed', 'woosea-feed'), 'manage_options', __FILE__, 'woosea_generate_pages');
285
  add_submenu_page(__FILE__, __('Manage feeds', 'woosea-feed'), __('Manage feeds', 'woosea-feed'), 'manage_options', 'woosea_manage_feed', 'woosea_manage_feed');
286
+ add_submenu_page(__FILE__, __('Settings', 'woosea-feed'), __('Settings', 'woosea-feed'), 'manage_options', 'woosea_manage_settings', 'woosea_manage_settings');
287
+ add_submenu_page(__FILE__, __('Upgrade to Elite', 'woosea-feed'), __('Upgrade to Elite', 'woosea-feed'), 'manage_options', 'woosea_upgrade_elite', 'woosea_upgrade_elite');
288
  }
289
 
290
  /**
311
  }
312
  add_action( 'wp_ajax_woosea_ajax', 'woosea_ajax' );
313
 
314
+ /**
315
+ * Map categories to the correct Google Shopping category taxonomy
316
+ */
317
+ function woosea_add_cat_mapping() {
318
+ $rowCount = sanitize_text_field($_POST['rowCount']);
319
+ $className = sanitize_text_field($_POST['className']);
320
+ $map_to_category = sanitize_text_field($_POST['map_to_category']);
321
+ $project_hash = sanitize_text_field($_POST['project_hash']);
322
+ $criteria = sanitize_text_field($_POST['criteria']);
323
+ $status_mapping = "false";
324
+
325
+ $project = WooSEA_Update_Project::get_project_data(sanitize_text_field($project_hash));
326
+
327
+ // This is during the configuration of a new feed
328
+ if(empty($project)){
329
+ $project_temp = get_option( 'channel_project' );
330
+ $project['mappings'][$rowCount]['rowCount'] = $rowCount;
331
+ $project['mappings'][$rowCount]['categoryId'] = $rowCount;
332
+ $project['mappings'][$rowCount]['criteria'] = $criteria;
333
+ $project['mappings'][$rowCount]['map_to_category'] = $map_to_category;
334
+ $project_fill = array_merge($project_temp, $project);
335
+ update_option( 'channel_project',$project_fill,'','yes');
336
+ $status_mapping = "true";
337
+ // This is updating an existing product feed
338
+ } else {
339
+ $project['mappings'][$rowCount]['rowCount'] = $rowCount;
340
+ $project['mappings'][$rowCount]['categoryId'] = $rowCount;
341
+ $project['mappings'][$rowCount]['criteria'] = $criteria;
342
+ $project['mappings'][$rowCount]['map_to_category'] = $map_to_category;
343
+
344
+ $project_updated = WooSEA_Update_Project::update_project_data($project);
345
+ $status_mapping = "true";
346
+ }
347
+
348
+ $data = array (
349
+ 'rowCount' => $rowCount,
350
+ 'className' => $className,
351
+ 'map_to_category' => $map_to_category,
352
+ 'status_mapping' => $status_mapping,
353
+ );
354
+
355
+ echo json_encode($data);
356
+ wp_die();
357
+ }
358
+ add_action( 'wp_ajax_woosea_add_cat_mapping', 'woosea_add_cat_mapping' );
359
+
360
+ /**
361
+ * Function to register a succesfull license activation
362
+ */
363
+ function woosea_register_license(){
364
+ $license_valid = sanitize_text_field($_POST['license_valid']);
365
+ $license_created = sanitize_text_field($_POST['license_created']);
366
+ $message = sanitize_text_field($_POST['message']);
367
+ $message_type = sanitize_text_field($_POST['message_type']);
368
+ $license_email = sanitize_text_field($_POST['license_email']);
369
+ $license_key = sanitize_text_field($_POST['license_key']);
370
+
371
+ $license_information = array (
372
+ 'license_valid' => $license_valid,
373
+ 'license_created' => $license_created,
374
+ 'message' => $message,
375
+ 'message_type' => $message_type,
376
+ 'license_email' => $license_email,
377
+ 'license_key' => $license_key
378
+ );
379
+ update_option("license_information", $license_information);
380
+
381
+ }
382
+ add_action( 'wp_ajax_woosea_register_license', 'woosea_register_license' );
383
+
384
+ /**
385
+ * Deactivate Elite license
386
+ */
387
+ function woosea_deactivate_license(){
388
+ delete_option( 'license_information' );
389
+ }
390
+ add_action( 'wp_ajax_woosea_deactivate_license', 'woosea_deactivate_license' );
391
+
392
+ /**
393
+ * Retrieve variation product id based on it attributes
394
+ **/
395
+ function woosea_find_matching_product_variation( $product, $attributes ) {
396
+
397
+ foreach( $attributes as $key => $value ) {
398
+ if( strpos( $key, 'attribute_' ) === 0 ) {
399
+ continue;
400
+ }
401
+ unset( $attributes[ $key ] );
402
+ $attributes[ sprintf( 'attribute_%s', $key ) ] = $value;
403
+ }
404
+
405
+ if( class_exists('WC_Data_Store') ) {
406
+ $data_store = WC_Data_Store::load( 'product' );
407
+ return $data_store->find_matching_product_variation( $product, $attributes );
408
+ } else {
409
+ return $product->get_matching_variation( $attributes );
410
+ }
411
+ }
412
+
413
+
414
+ /**
415
+ * Remove the price from the JSON-LD on variant product pages
416
+ * As WooCommerce shows the wrong price and it causes items
417
+ * to disapproved in Google's Merchant center because of it
418
+ */
419
+ function woosea_product_delete_meta_price( $product = null ) {
420
+
421
+ $markup_offer = array();
422
+ $structured_data_fix = get_option ('structured_data_fix');
423
+
424
+ if ( ! is_object( $product ) ) {
425
+ global $product;
426
+ }
427
+ if ( ! is_a( $product, 'WC_Product' ) ) {
428
+ return;
429
+ }
430
+ $shop_name = get_bloginfo( 'name' );
431
+ $shop_url = home_url();
432
+ $shop_currency = get_woocommerce_currency();
433
+
434
+ if($structured_data_fix == "yes"){
435
+
436
+ if ( '' !== $product->get_price() ) {
437
+ $product_id = get_the_id();
438
+
439
+ // Get product condition
440
+ $condition = ucfirst( get_post_meta( $product_id, '_woosea_condition', true ) );
441
+ if(!$condition){
442
+ $json_condition = "NewCondition";
443
+ } else {
444
+ $json_condition = $condition."Condition";
445
+ }
446
+
447
+ if ( $product->is_type( 'variable' ) ) {
448
+ // We should first check if there are any _GET parameters available
449
+ // When there are not we are on a variable product page but not on a specific variable one
450
+ // In that case we need to put in the AggregateOffer structured data
451
+ $variation_id = woosea_find_matching_product_variation( $product, $_GET );
452
+ $nr_get = count($_GET);
453
+
454
+ if($nr_get > 0){
455
+ $variable_product = wc_get_product($variation_id);
456
+
457
+ if(is_object( $variable_product ) ) {
458
+
459
+ $product_price = $variable_product->get_price();
460
+
461
+ // Get product condition
462
+ $condition = ucfirst( get_post_meta( $variation_id, '_woosea_condition', true ) );
463
+ if(!$condition){
464
+ $json_condition = "NewCondition";
465
+ } else {
466
+ $json_condition = $condition."Condition";
467
+ }
468
+
469
+ // Get stock status
470
+ $stock_status = $variable_product->get_stock_status();
471
+ if ($stock_status == "outofstock"){
472
+ $availability = "OutOfStock";
473
+ } else {
474
+ $availability = "InStock";
475
+ }
476
+
477
+ $markup_offer = array(
478
+ '@type' => 'Offer',
479
+ 'price' => $product_price,
480
+ 'priceCurrency' => $shop_currency,
481
+ 'itemCondition' => 'http://schema.org/'.$json_condition.'',
482
+ 'availability' => 'https://schema.org/'.$availability.'',
483
+ 'sku' => $product->get_sku(),
484
+ 'image' => wp_get_attachment_url( $product->get_image_id() ),
485
+ 'description' => $product->get_description(),
486
+ 'seller' => array(
487
+ '@type' => 'Organization',
488
+ 'name' => $shop_name,
489
+ 'url' => $shop_url,
490
+ ),
491
+ );
492
+ } else {
493
+ // AggregateOffer
494
+ $prices = $product->get_variation_prices();
495
+ $lowest = reset( $prices['price'] );
496
+ $highest = end( $prices['price'] );
497
+
498
+ if ( $lowest === $highest ) {
499
+ $markup_offer = array(
500
+ '@type' => 'Offer',
501
+ 'price' => wc_format_decimal( $lowest, wc_get_price_decimals() ),
502
+ 'priceCurrency' => $shop_currency,
503
+ 'itemCondition' => 'http://schema.org/'.$json_condition.'',
504
+ 'availability' => 'https://schema.org/' . $stock = ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' ),
505
+ 'sku' => $product->get_sku(),
506
+ 'image' => wp_get_attachment_url( $product->get_image_id() ),
507
+ 'description' => $product->get_description(),
508
+ 'seller' => array(
509
+ '@type' => 'Organization',
510
+ 'name' => $shop_name,
511
+ 'url' => $shop_url,
512
+ ),
513
+ );
514
+ } else {
515
+ $markup_offer = array(
516
+ '@type' => 'AggregateOffer',
517
+ 'lowPrice' => wc_format_decimal( $lowest, wc_get_price_decimals() ),
518
+ 'highPrice' => wc_format_decimal( $highest, wc_get_price_decimals() ),
519
+ 'priceCurrency' => $shop_currency,
520
+ 'itemCondition' => 'http://schema.org/'.$json_condition.'',
521
+ 'availability' => 'https://schema.org/' . $stock = ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' ),
522
+ 'sku' => $product->get_sku(),
523
+ 'image' => wp_get_attachment_url( $product->get_image_id() ),
524
+ 'description' => $product->get_description(),
525
+ 'seller' => array(
526
+ '@type' => 'Organization',
527
+ 'name' => $shop_name,
528
+ 'url' => $shop_url,
529
+ ),
530
+ );
531
+ }
532
+ }
533
+ } else {
534
+ // When there are no parameters in the URL (so for normal users, not coming via Google Shopping URL's) show the old WooCommwerce JSON
535
+ $prices = $product->get_variation_prices();
536
+ $lowest = reset( $prices['price'] );
537
+ $highest = end( $prices['price'] );
538
+
539
+ if ( $lowest === $highest ) {
540
+ $markup_offer = array(
541
+ '@type' => 'Offer',
542
+ 'price' => wc_format_decimal( $lowest, wc_get_price_decimals() ),
543
+ );
544
+ } else {
545
+ $markup_offer = array(
546
+ '@type' => 'AggregateOffer',
547
+ 'lowPrice' => wc_format_decimal( $lowest, wc_get_price_decimals() ),
548
+ 'highPrice' => wc_format_decimal( $highest, wc_get_price_decimals() ),
549
+ );
550
+ }
551
+
552
+ $markup_offer += array(
553
+ 'priceCurrency' => $shop_currency,
554
+ 'availability' => 'https://schema.org/' . ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' ),
555
+ 'seller' => array(
556
+ '@type' => 'Organization',
557
+ 'name' => $shop_name,
558
+ 'url' => $shop_url,
559
+ ),
560
+ );
561
+
562
+ }
563
+ } else {
564
+ $markup_offer = array(
565
+ '@type' => 'Offer',
566
+ 'price' => wc_format_decimal( $product->get_price(), wc_get_price_decimals() ),
567
+ 'priceCurrency' => $shop_currency,
568
+ 'itemCondition' => 'http://schema.org/'.$json_condition.'',
569
+ 'availability' => 'https://schema.org/' . $stock = ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' ),
570
+ 'sku' => $product->get_sku(),
571
+ 'image' => wp_get_attachment_url( $product->get_image_id() ),
572
+ 'description' => $product->get_description(),
573
+ 'seller' => array(
574
+ '@type' => 'Organization',
575
+ 'name' => $shop_name,
576
+ 'url' => $shop_url,
577
+ ),
578
+ );
579
+ }
580
+ }
581
+ } else {
582
+ // Just use the old WooCommerce buggy setting
583
+ if ( '' !== $product->get_price() ) {
584
+
585
+ if ( $product->is_type( 'variable' ) ) {
586
+ $prices = $product->get_variation_prices();
587
+ $lowest = reset( $prices['price'] );
588
+ $highest = end( $prices['price'] );
589
+
590
+ if ( $lowest === $highest ) {
591
+
592
+ $markup_offer = array(
593
+ '@type' => 'Offer',
594
+ 'price' => wc_format_decimal( $lowest, wc_get_price_decimals() ),
595
+ 'priceCurrency' => $shop_currency,
596
+ );
597
+
598
+
599
+ } else {
600
+ $markup_offer = array(
601
+ '@type' => 'AggregateOffer',
602
+ 'lowPrice' => wc_format_decimal( $lowest, wc_get_price_decimals() ),
603
+ 'highPrice' => wc_format_decimal( $highest, wc_get_price_decimals() ),
604
+ 'priceCurrency' => $shop_currency,
605
+ 'availability' => 'https://schema.org/' . ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' ),
606
+ 'seller' => array(
607
+ '@type' => 'Organization',
608
+ 'name' => $shop_name,
609
+ 'url' => $shop_url,
610
+ ),
611
+ );
612
+ }
613
+ } else {
614
+ $markup_offer = array(
615
+ '@type' => 'Offer',
616
+ 'price' => wc_format_decimal( $product->get_price(), wc_get_price_decimals() ),
617
+ 'priceCurrency' => $shop_currency,
618
+ 'availability' => 'https://schema.org/' . ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' ),
619
+ 'seller' => array(
620
+ '@type' => 'Organization',
621
+ 'name' => $shop_name,
622
+ 'url' => $shop_url,
623
+ ),
624
+ );
625
+ }
626
+ }
627
+ }
628
+ return $markup_offer;
629
+ }
630
+ add_filter( 'woocommerce_structured_data_product_offer', 'woosea_product_delete_meta_price' );
631
+
632
  /**
633
  * Get the shipping zone countries and ID's
634
  */
797
  }
798
  add_action( 'wp_ajax_woosea_project_status', 'woosea_project_status' );
799
 
800
+ /**
801
+ * Register interaction with the review request notification
802
+ * We do not want to keep bothering our users with the notification
803
+ */
804
+ function woosea_review_notification() {
805
+ // Update review notification status
806
+ update_option( 'woosea_review_interaction', 'yes');
807
+ }
808
+ add_action( 'wp_ajax_woosea_review_notification', 'woosea_review_notification' );
809
+
810
+ /**
811
+ * Register interaction with the license notification
812
+ * We do not want to keep bothering our users with the notification
813
+ */
814
+ function woosea_license_notification() {
815
+ // Update review notification status
816
+ update_option( 'woosea_license_notification_closed', 'yes');
817
+ }
818
+ add_action( 'wp_ajax_woosea_license_notification', 'woosea_license_notification' );
819
+
820
+ /**
821
+ * This function enables the setting to fix the
822
+ * WooCommerce structured data bug
823
+ */
824
+ function woosea_enable_structured_data (){
825
+ $status = sanitize_text_field($_POST['status']);
826
+ if ($status == "off"){
827
+ update_option( 'structured_data_fix', 'no', 'yes');
828
+ } else {
829
+ update_option( 'structured_data_fix', 'yes', 'yes');
830
+ }
831
+ }
832
+ add_action( 'wp_ajax_woosea_enable_structured_data', 'woosea_enable_structured_data' );
833
+
834
+
835
+ /**
836
+ * This function enables the setting to add
837
+ * identifiers GTIN, MPN, EAN, UPC, Brand and Condition
838
+ */
839
+ function woosea_add_identifiers (){
840
+ $status = sanitize_text_field($_POST['status']);
841
+ if ($status == "off"){
842
+ update_option( 'add_unique_identifiers', 'no', 'yes');
843
+ } else {
844
+ update_option( 'add_unique_identifiers', 'yes', 'yes');
845
+ }
846
+ }
847
+ add_action( 'wp_ajax_woosea_add_identifiers', 'woosea_add_identifiers' );
848
+
849
+ /**
850
+ * This function add the actual fields to the edit product page for single products
851
+ * identifiers GTIN, MPN, EAN, UPC, Brand and Condition
852
+ */
853
+ function woosea_custom_general_fields() {
854
+ global $woocommerce, $post;
855
+
856
+ // Check if the option is enabled or not in the pluggin settings
857
+ if( get_option('add_unique_identifiers') == "yes" ){
858
+
859
+ echo '<div id="woosea_attr" class="options_group">';
860
+
861
+ // Brand field
862
+ woocommerce_wp_text_input(
863
+ array(
864
+ 'id' => '_woosea_brand',
865
+ 'label' => __( 'Brand', 'woocommerce' ),
866
+ 'desc_tip' => 'true',
867
+ 'value' => get_post_meta( $post->ID, '_woosea_brand', true ),
868
+ 'description' => __( 'Enter the product Brand here.', 'woocommerce' )
869
+ )
870
+ );
871
+
872
+ echo '</div>';
873
+ echo '<div id="woosea_attr" class="options_group show_if_simple show_if_external">';
874
+
875
+ // Global Trade Item Number (GTIN) Field
876
+ woocommerce_wp_text_input(
877
+ array(
878
+ 'id' => '_woosea_gtin',
879
+ 'label' => __( 'GTIN', 'woocommerce' ),
880
+ 'desc_tip' => 'true',
881
+ 'description' => __( 'Enter the product Global Trade Item Number (GTIN) here.', 'woocommerce' ),
882
+ )
883
+ );
884
+
885
+ // MPN Field
886
+ woocommerce_wp_text_input(
887
+ array(
888
+ 'id' => '_woosea_mpn',
889
+ 'label' => __( 'MPN', 'woocommerce' ),
890
+ 'desc_tip' => 'true',
891
+ 'description' => __( 'Enter the manufacturer product number', 'woocommerce' ),
892
+ )
893
+ );
894
+
895
+ // Universal Product Code (UPC) Field
896
+ woocommerce_wp_text_input(
897
+ array(
898
+ 'id' => '_woosea_upc',
899
+ 'label' => __( 'UPC', 'woocommerce' ),
900
+ 'desc_tip' => 'true',
901
+ 'description' => __( 'Enter the Universal Product Code (UPC) here.', 'woocommerce' ),
902
+ )
903
+ );
904
+
905
+ // International Article Number (EAN) Field
906
+ woocommerce_wp_text_input(
907
+ array(
908
+ 'id' => '_woosea_ean',
909
+ 'label' => __( 'EAN', 'woocommerce' ),
910
+ 'desc_tip' => 'true',
911
+ 'description' => __( 'Enter the International Article Number (EAN) here.', 'woocommerce' ),
912
+ )
913
+ );
914
+
915
+ // Optimized product custom title Field
916
+ woocommerce_wp_text_input(
917
+ array(
918
+ 'id' => '_woosea_optimized_title',
919
+ 'label' => __( 'Optimized title', 'woocommerce' ),
920
+ 'desc_tip' => 'true',
921
+ 'description' => __( 'Enter a optimized product title.', 'woocommerce' ),
922
+ )
923
+ );
924
+
925
+ // Add product condition drop-down
926
+ woocommerce_wp_select(
927
+ array(
928
+ 'id' => '_woosea_condition',
929
+ 'label' => __( 'Product condition', 'woocommerce' ),
930
+ 'desc_tip' => 'true',
931
+ 'description' => __( 'Select the product condition.', 'woocommerce' ),
932
+ 'options' => array (
933
+ '' => __( '', 'woocommerce' ),
934
+ 'new' => __( 'new', 'woocommerce' ),
935
+ 'refurbished' => __( 'refurbished', 'woocommerce' ),
936
+ 'used' => __( 'used', 'woocommerce' ),
937
+ 'damaged' => __( 'damaged', 'woocommerce' ),
938
+ )
939
+ )
940
+ );
941
+
942
+ // Unit pricing measure Field
943
+ woocommerce_wp_text_input(
944
+ array(
945
+ 'id' => '_woosea_unit_pricing_measure',
946
+ 'label' => __( 'Unit pricing measure', 'woocommerce' ),
947
+ 'desc_tip' => 'true',
948
+ 'description' => __( 'Enter an unit pricing measure.', 'woocommerce' ),
949
+ )
950
+ );
951
+
952
+ // Unit pricing base measure Field
953
+ woocommerce_wp_text_input(
954
+ array(
955
+ 'id' => '_woosea_unit_pricing_base_measure',
956
+ 'label' => __( 'Unit pricing base measure', 'woocommerce' ),
957
+ 'desc_tip' => 'true',
958
+ 'description' => __( 'Enter an unit pricing base measure.', 'woocommerce' ),
959
+ )
960
+ );
961
+
962
+ // Exclude product from feed
963
+ woocommerce_wp_checkbox(
964
+ array(
965
+ 'id' => '_woosea_exclude_product',
966
+ 'label' => __( 'Exclude from feeds', 'woocommerce' ),
967
+ 'desc_tip' => 'true',
968
+ 'description' => __( 'Check this box if you want this product to be excluded from product feeds.', 'woocommerce' ),
969
+ )
970
+ );
971
+
972
+ echo '</div>';
973
+ }
974
+ }
975
+ add_action( 'woocommerce_product_options_general_product_data', 'woosea_custom_general_fields' );
976
+
977
+ /**
978
+ * This function saves the input from the extra fields on the single product edit page
979
+ */
980
+ function woosea_save_custom_general_fields($post_id){
981
+
982
+ $woocommerce_brand = $_POST['_woosea_brand'];
983
+ $woocommerce_gtin = $_POST['_woosea_gtin'];
984
+ $woocommerce_upc = $_POST['_woosea_upc'];
985
+ $woocommerce_mpn = $_POST['_woosea_mpn'];
986
+ $woocommerce_ean = $_POST['_woosea_ean'];
987
+ $woocommerce_title = $_POST['_woosea_optimized_title'];
988
+ $woocommerce_unit_pricing_measure = $_POST['_woosea_unit_pricing_measure'];
989
+ $woocommerce_unit_pricing_base_measure = $_POST['_woosea_unit_pricing_base_measure'];
990
+ $woocommerce_condition = $_POST['_woosea_condition'];
991
+ if(!empty($_POST['_woosea_exclude_product'])){
992
+ $woocommerce_exclude_product = $_POST['_woosea_exclude_product'];
993
+ } else {
994
+ $woocommerce_exclude_product = "no";;
995
+ }
996
+
997
+ if(isset($woocommerce_brand))
998
+ update_post_meta( $post_id, '_woosea_brand', esc_attr($woocommerce_brand));
999
+
1000
+ if(isset($woocommerce_mpn))
1001
+ update_post_meta( $post_id, '_woosea_mpn', esc_attr($woocommerce_mpn));
1002
+
1003
+ if(isset($woocommerce_upc))
1004
+ update_post_meta( $post_id, '_woosea_upc', esc_attr($woocommerce_upc));
1005
+
1006
+ if(isset($woocommerce_ean))
1007
+ update_post_meta( $post_id, '_woosea_ean', esc_attr($woocommerce_ean));
1008
+
1009
+ if(isset($woocommerce_gtin))
1010
+ update_post_meta( $post_id, '_woosea_gtin', esc_attr($woocommerce_gtin));
1011
+
1012
+ if(isset($woocommerce_title))
1013
+ update_post_meta( $post_id, '_woosea_optimized_title', esc_attr($woocommerce_title));
1014
+
1015
+ if(isset($woocommerce_unit_pricing_measure))
1016
+ update_post_meta( $post_id, '_woosea_unit_pricing_measure', esc_attr($woocommerce_unit_pricing_measure));
1017
+
1018
+ if(isset($woocommerce_unit_pricing_base_measure))
1019
+ update_post_meta( $post_id, '_woosea_unit_pricing_base_measure', esc_attr($woocommerce_unit_pricing_base_measure));
1020
+
1021
+ if(isset($woocommerce_condition))
1022
+ update_post_meta( $post_id, '_woosea_condition', esc_attr($woocommerce_condition));
1023
+
1024
+ if(isset($woocommerce_exclude_product))
1025
+ update_post_meta( $post_id, '_woosea_exclude_product', esc_attr($woocommerce_exclude_product));
1026
+ }
1027
+ add_action( 'woocommerce_process_product_meta', 'woosea_save_custom_general_fields' );
1028
+
1029
+ /**
1030
+ * Create the unique identifier fields for variation products
1031
+ */
1032
+ function woosea_custom_variable_fields( $loop, $variation_id, $variation ) {
1033
+
1034
+ // Check if the option is enabled or not in the pluggin settings
1035
+ if( get_option('add_unique_identifiers') == "yes" ){
1036
+
1037
+ // Variation Brand field
1038
+ woocommerce_wp_text_input(
1039
+ array(
1040
+ 'id' => '_woosea_variable_brand['.$loop.']',
1041
+ 'label' => __( '<br>Brand', 'woocommerce' ),
1042
+ 'placeholder' => 'Parent Brand',
1043
+ 'desc_tip' => 'true',
1044
+ 'description' => __( 'Enter the product Brand here.', 'woocommerce' ),
1045
+ 'value' => get_post_meta($variation->ID, '_woosea_brand', true),
1046
+ 'wrapper_class' => 'form-row-full',
1047
+ )
1048
+ );
1049
+
1050
+ // Variation GTIN field
1051
+ woocommerce_wp_text_input(
1052
+ array(
1053
+ 'id' => '_woosea_variable_gtin['.$loop.']',
1054
+ 'label' => __( '<br>GTIN', 'woocommerce' ),
1055
+ 'placeholder' => 'GTIN',
1056
+ 'desc_tip' => 'true',
1057
+ 'description' => __( 'Enter the product GTIN here.', 'woocommerce' ),
1058
+ 'value' => get_post_meta($variation->ID, '_woosea_gtin', true),
1059
+ 'wrapper_class' => 'form-row-last',
1060
+ )
1061
+ );
1062
+
1063
+ // Variation MPN field
1064
+ woocommerce_wp_text_input(
1065
+ array(
1066
+ 'id' => '_woosea_variable_mpn['.$loop.']',
1067
+ 'label' => __( '<br>MPN', 'woocommerce' ),
1068
+ 'placeholder' => 'Manufacturer Product Number',
1069
+ 'desc_tip' => 'true',
1070
+ 'description' => __( 'Enter the product UPC here.', 'woocommerce' ),
1071
+ 'value' => get_post_meta($variation->ID, '_woosea_mpn', true),
1072
+ 'wrapper_class' => 'form-row-first',
1073
+ )
1074
+ );
1075
+
1076
+ // Variation UPC field
1077
+ woocommerce_wp_text_input(
1078
+ array(
1079
+ 'id' => '_woosea_variable_upc['.$loop.']',
1080
+ 'label' => __( '<br>UPC', 'woocommerce' ),
1081
+ 'placeholder' => 'UPC',
1082
+ 'desc_tip' => 'true',
1083
+ 'description' => __( 'Enter the product UPC here.', 'woocommerce' ),
1084
+ 'value' => get_post_meta($variation->ID, '_woosea_upc', true),
1085
+ 'wrapper_class' => 'form-row-last',
1086
+ )
1087
+ );
1088
+
1089
+ // Variation EAN field
1090
+ woocommerce_wp_text_input(
1091
+ array(
1092
+ 'id' => '_woosea_variable_ean['.$loop.']',
1093
+ 'label' => __( '<br>EAN', 'woocommerce' ),
1094
+ 'placeholder' => 'EAN',
1095
+ 'desc_tip' => 'true',
1096
+ 'description' => __( 'Enter the product EAN here.', 'woocommerce' ),
1097
+ 'value' => get_post_meta($variation->ID, '_woosea_ean', true),
1098
+ 'wrapper_class' => 'form-row-first',
1099
+ )
1100
+ );
1101
+
1102
+ // Variation Unit pricing measure field
1103
+ woocommerce_wp_text_input(
1104
+ array(
1105
+ 'id' => '_woosea_variable_unit_pricing_measure['.$loop.']',
1106
+ 'label' => __( '<br>Unit pricing measure', 'woocommerce' ),
1107
+ 'placeholder' => 'Unit pricing measure',
1108
+ 'desc_tip' => 'true',
1109
+ 'description' => __( 'Enter the product Unit pricing measure here.', 'woocommerce' ),
1110
+ 'value' => get_post_meta($variation->ID, '_woosea_unit_pricing_measure', true),
1111
+ 'wrapper_class' => 'form-row-first',
1112
+ )
1113
+ );
1114
+
1115
+ // Variation Unit pricing base measure field
1116
+ woocommerce_wp_text_input(
1117
+ array(
1118
+ 'id' => '_woosea_variable_unit_pricing_base_measure['.$loop.']',
1119
+ 'label' => __( '<br>Unit pricing base measure', 'woocommerce' ),
1120
+ 'placeholder' => 'Unit pricing base measure',
1121
+ 'desc_tip' => 'true',
1122
+ 'description' => __( 'Enter the product Unit pricing base measure here.', 'woocommerce' ),
1123
+ 'value' => get_post_meta($variation->ID, '_woosea_unit_pricing_base_measure', true),
1124
+ 'wrapper_class' => 'form-row-first',
1125
+ )
1126
+ );
1127
+
1128
+ // Variation optimized title field
1129
+ woocommerce_wp_text_input(
1130
+ array(
1131
+ 'id' => '_woosea_optimized_title['.$loop.']',
1132
+ 'label' => __( '<br>Optimized title', 'woocommerce' ),
1133
+ 'placeholder' => 'Optimized title',
1134
+ 'desc_tip' => 'true',
1135
+ 'description' => __( 'Enter a optimized product title here.', 'woocommerce' ),
1136
+ 'value' => get_post_meta($variation->ID, '_woosea_optimized_title', true),
1137
+ 'wrapper_class' => 'form-row-last',
1138
+ )
1139
+ );
1140
+
1141
+ // Add product condition drop-down
1142
+ woocommerce_wp_select(
1143
+ array(
1144
+ 'id' => '_woosea_condition['.$loop.']',
1145
+ 'label' => __( 'Product condition', 'woocommerce' ),
1146
+ 'placeholder' => 'Product condition',
1147
+ 'desc_tip' => 'true',
1148
+ 'description' => __( 'Select the product condition.', 'woocommerce' ),
1149
+ 'value' => get_post_meta($variation->ID, '_woosea_condition', true),
1150
+ 'wrapper_class' => 'form-row form-row-full',
1151
+ 'options' => array (
1152
+ '' => __( '', 'woocommerce' ),
1153
+ 'new' => __( 'new', 'woocommerce' ),
1154
+ 'refurbished' => __( 'refurbished', 'woocommerce' ),
1155
+ 'used' => __( 'used', 'woocommerce' ),
1156
+ 'damaged' => __( 'damaged', 'woocommerce' ),
1157
+ )
1158
+ )
1159
+ );
1160
+
1161
+ // Exclude product from feed
1162
+ woocommerce_wp_checkbox(
1163
+ array(
1164
+ 'id' => '_woosea_exclude_product['.$loop.']',
1165
+ 'label' => __( '&nbsp;Exclude from feeds', 'woocommerce' ),
1166
+ 'placeholder' => 'Exclude from feeds',
1167
+ 'desc_tip' => 'true',
1168
+ 'description' => __( 'Check this box if you want this product to be excluded from product feeds.', 'woocommerce' ),
1169
+ 'value' => get_post_meta($variation->ID, '_woosea_exclude_product', true),
1170
+ )
1171
+ );
1172
+ }
1173
+ }
1174
+ add_action( 'woocommerce_product_after_variable_attributes', 'woosea_custom_variable_fields', 10, 3 );
1175
+
1176
+ /**
1177
+ * Save the unique identifier fields for variation products
1178
+ */
1179
+ function woosea_save_custom_variable_fields( $post_id ) {
1180
+
1181
+ if (isset( $_POST['variable_sku'] ) ) {
1182
+
1183
+ $variable_sku = $_POST['variable_sku'];
1184
+ $variable_post_id = $_POST['variable_post_id'];
1185
+
1186
+ $max_loop = max( array_keys( $_POST['variable_post_id'] ) );
1187
+
1188
+ for ( $i = 0; $i <= $max_loop; $i++ ) {
1189
+
1190
+ if ( ! isset( $variable_post_id[ $i ] ) ) {
1191
+ continue;
1192
+ }
1193
+
1194
+ // Brand Field
1195
+ $_brand = $_POST['_woosea_variable_brand'];
1196
+ $variation_id = (int) $variable_post_id[$i];
1197
+ if ( isset( $_brand[$i] ) ) {
1198
+ update_post_meta( $variation_id, '_woosea_brand', stripslashes( $_brand[$i]));
1199
+ }
1200
+
1201
+
1202
+ // MPN Field
1203
+ $_mpn = $_POST['_woosea_variable_mpn'];
1204
+ $variation_id = (int) $variable_post_id[$i];
1205
+ if ( isset( $_mpn[$i] ) ) {
1206
+ update_post_meta( $variation_id, '_woosea_mpn', stripslashes( $_mpn[$i]));
1207
+ }
1208
+
1209
+ // UPC Field
1210
+ $_upc = $_POST['_woosea_variable_upc'];
1211
+ $variation_id = (int) $variable_post_id[$i];
1212
+ if ( isset( $_upc[$i] ) ) {
1213
+ update_post_meta( $variation_id, '_woosea_upc', stripslashes( $_upc[$i]));
1214
+ }
1215
+
1216
+ // EAN Field
1217
+ $_ean = $_POST['_woosea_variable_ean'];
1218
+ $variation_id = (int) $variable_post_id[$i];
1219
+ if ( isset( $_ean[$i] ) ) {
1220
+ update_post_meta( $variation_id, '_woosea_ean', stripslashes( $_ean[$i]));
1221
+ }
1222
+
1223
+ // GTIN Field
1224
+ $_gtin = $_POST['_woosea_variable_gtin'];
1225
+ $variation_id = (int) $variable_post_id[$i];
1226
+ if ( isset( $_gtin[$i] ) ) {
1227
+ update_post_meta( $variation_id, '_woosea_gtin', stripslashes( $_gtin[$i]));
1228
+ }
1229
+
1230
+ // Unit pricing measure Field
1231
+ $_pricing_measure = $_POST['_woosea_variable_unit_pricing_measure'];
1232
+ $variation_id = (int) $variable_post_id[$i];
1233
+ if ( isset( $_pricing_measure[$i] ) ) {
1234
+ update_post_meta( $variation_id, '_woosea_unit_pricing_measure', stripslashes( $_pricing_measure[$i]));
1235
+ }
1236
+
1237
+ // Unit pricing base measure Field
1238
+ $_pricing_base = $_POST['_woosea_variable_unit_pricing_base_measure'];
1239
+ $variation_id = (int) $variable_post_id[$i];
1240
+ if ( isset( $_pricing_base[$i] ) ) {
1241
+ update_post_meta( $variation_id, '_woosea_unit_pricing_base_measure', stripslashes( $_pricing_base[$i]));
1242
+ }
1243
+
1244
+ // Optimized title Field
1245
+ $_opttitle = $_POST['_woosea_optimized_title'];
1246
+ $variation_id = (int) $variable_post_id[$i];
1247
+ if ( isset( $_opttitle[$i] ) ) {
1248
+ update_post_meta( $variation_id, '_woosea_optimized_title', stripslashes( $_opttitle[$i]));
1249
+ }
1250
+
1251
+ // Product condition Field
1252
+ $_condition = $_POST['_woosea_condition'];
1253
+ $variation_id = (int) $variable_post_id[$i];
1254
+ if ( isset( $_condition[$i] ) ) {
1255
+ update_post_meta( $variation_id, '_woosea_condition', stripslashes( $_condition[$i]));
1256
+ }
1257
+
1258
+ // Exclude product from feed
1259
+ if(empty($_POST['_woosea_exclude_product'])){
1260
+ $_excludeproduct[$i] = "no";
1261
+ } else {
1262
+ $_excludeproduct = $_POST['_woosea_exclude_product'];
1263
+ }
1264
+ $variation_id = (int) $variable_post_id[$i];
1265
+ if ( isset( $_excludeproduct[$i] ) ) {
1266
+ update_post_meta( $variation_id, '_woosea_exclude_product', stripslashes( $_excludeproduct[$i]));
1267
+ }
1268
+ }
1269
+ }
1270
+ }
1271
+ add_action( 'woocommerce_save_product_variation', 'woosea_save_custom_variable_fields', 10, 1 );
1272
+
1273
  /**
1274
  * Returns the user ID of the user which is used as the
1275
  * login for AdTribes support. The user is created here if it doesn't
1287
  if($status == "off"){
1288
  $user_id = $user->ID;
1289
  $del_user = wp_delete_user($user_id);
1290
+ update_option('woosea_support_user', 'no', 'yes');
1291
  } else {
1292
  $user_id = $user->ID;
1293
+ update_option('woosea_support_user', 'yes', 'yes');
1294
  }
1295
  } else {
1296
  $user_pass = wp_generate_password( 12 );
1305
  if ( !( $maybe_user_id instanceof WP_Error ) ) {
1306
  $user_id = $maybe_user_id;
1307
 
1308
+ update_option('woosea_support_user', 'yes', 'yes');
1309
+
1310
  // notify admin
1311
  $user = get_userdata( $user_id );
1312
  $blogname = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
1320
 
1321
  // notify AdTribes.io support
1322
  $websitehome = wp_specialchars_decode( get_option( 'home' ), ENT_QUOTES );
1323
+ $admin_login = wp_login_url( get_permalink() );
1324
+ $websiteadmin = $admin_login;
1325
 
1326
  $message = sprintf( __( 'AdTribes.io support user created on %s:', WOOCOMMERCESEA_PLUGIN_NAME ), $blogname ) . "\r\n\r\n";
1327
  $message .= sprintf( __( 'Website: %s', WOOCOMMERCESEA_PLUGIN_NAME ), $websitehome ) . "\r\n\r\n";
1329
  $message .= sprintf( __( 'Username: %s', WOOCOMMERCESEA_PLUGIN_NAME ), $user->user_login ) . "\r\n\r\n";
1330
  $message .= sprintf( __( 'Password: %s', WOOCOMMERCESEA_PLUGIN_NAME ), $user_pass ) . "\r\n\r\n";
1331
 
1332
+ $message .= __( 'The user has the role of a Admin.', WOOCOMMERCESEA_PLUGIN_NAME ) . "\r\n";
1333
 
1334
  @wp_mail( 'support@adtribes.io', sprintf( __( '[%s] AdTribes.io Support User', WOOCOMMERCESEA_PLUGIN_NAME ), $blogname ), $message);
1335
  }
1393
  }
1394
  add_action( 'woosea_update_project_stats', 'woosea_update_project_history',1,1 );
1395
 
1396
+
1397
+ /**
1398
+ * Get the attribute mapping helptexts
1399
+ */
1400
+ function woosea_fieldmapping_dialog_helptext(){
1401
+ $field = sanitize_text_field($_POST['field']);
1402
+
1403
+ switch ($field) {
1404
+ case "g:id";
1405
+ $helptext = "(Required field) The g:id field is used to uniquely identify each product. The g:id needs to be unique and remain the same forever. Google advises to map the g:id field to a SKU value, however since this field is not always present nor always filled we suggest you map the 'Product Id' field to g:id.";
1406
+ break;
1407
+ case "g:title";
1408
+ $helptext = "(Required field) The g:title field should clearly identify the product you are selling. We suggest you map this field to your 'Product name'.";
1409
+ break;
1410
+ case "g:description";
1411
+ $helptext = "(Required field) The g:description field should tell users about your product. We suggest you map this field to your 'Product description' or 'Product short description'";
1412
+ break;
1413
+ case "g:link";
1414
+ $helptext = "(Required field) The g:link field should be filled with the landing page on your website. We suggest you map this field to your 'Link' attribute.";
1415
+ break;
1416
+ case "g:image_link";
1417
+ $helptext = "(Required field) Include the URL for your main product image with the g:image_link attribute. We suggest you map this field to your 'Main image' attribute.";
1418
+ break;
1419
+ case "g:definition";
1420
+ $helptext = "(Required field) Use the g:availability attribute to tell users and Google whether you have a product in stock. We suggest you map this field to your 'Availability' attribute.";
1421
+ break;
1422
+ case "g:price";
1423
+ $helptext = "(Required field) Use the g:price attribute to tell users how much you are charging for your product. We suggest you map this field to your 'Price' attribute. When a product is on sale the plugin will automatically get the sale price instead of the normal base price. Also, make sure you use a currency pre- or suffix as this is required by Google when you have not configured a currency in your Google Merchant center. The plugin automatically determines your relevant currency and puts this in the price prefix field.";
1424
+ break;
1425
+ case "g:google_product_category";
1426
+ $helptext = "(Required for some product categories) Use the g:google_product_category attribute to indicate the category of your item based on the Google product taxonomy. Map this field to your 'Category' attribute. In the next configuration step you will be able to map your categories to Google's category taxonomy. Categorizing your product helps ensure that your ad is shown with the right search results.";
1427
+ break;
1428
+ case "g:brand";
1429
+ $helptext = "Use the g:brand attribute to indicate the product's brand name. The brand is used to help identify your product and will be shown to users who view your ad. g:brand is required for each product with a clearly associated brand or manufacturer. If the product doesn't have a clearly associated brand (e.g. movies, books, music) or is a custom-made product (e.g. art, custom t-shirts, novelty products and handmade products), the attribute is optional. As WooCommerce does not have a brand attribute out of the box you will probably have to map the g:brand field to a custom/dynamic field or product attribute.";
1430
+ break;
1431
+ case "g:gtin";
1432
+ $helptext = "(Required for all products with a GTIN assigned by the manufacturer). This specific number helps Google to make your ad richer and easier for users to find. Products submitted without any unique product identifiers are difficult to classify and may not be able to take advantage of all Google Shopping features. Several different types of ID numbers are considered a GTIN, for example: EAN, UPC, JAN, ISBN, IFT-14. Most likely you have configured custom/dynamic or product attribute that you need to map to the g:gtin field.";
1433
+ break;
1434
+ case "g:mpn";
1435
+ $helptext = "(Required for all products without a manufacturer-assigned GTIN.) USe the mpn attribute to submit your product's Manufacturer Part Number (MPN). MPNs are used to uniquely identify a specific product among all products from the same manufacturer. Users might search Google Shopping specifically for an MPN, so providing the MPN can help ensure that your product is shown in relevant situations. When a product doesn't have a clearly associated mpn or is a custom-made product (e.g. art, custom t-shirts, novelty products and handmade products), the attribute is optional.";
1436
+ break;
1437
+ case "g:identifier_exists";
1438
+ $helptext = "(Required only for new products that don’t have <b>gtin and brand</b> or <b>mpn and brand</b>.) Use the g:identifier_exists attribute to indicate that unique product identifiers aren’t available for your product. Unique product identifiers include gtin, mpn, and brand. The plugin automatically determines if the value for a product is 'no' or 'yes' when you set the g:identifier_exists to 'Plugin calculation'.";
1439
+ break;
1440
+ case "g:condition";
1441
+ $helptext = "(Required) Tell users about the condition of the product you are selling. Supported values are: 'new', 'refurbished' and 'used'. We suggest you map this field to the 'Condition' attribute.";
1442
+ break;
1443
+ case "g:item_group_id";
1444
+ $helptext = "(Required for the following countries: Brazil, France, Germany, Japan, United Kingdom and the United States). The g:item_group_id is used to group product variants in your product data. We suggest you map the g:item_group_id to the 'Item group ID' attribute. The plugin automatically ads the correct value to this field and makes sure the 'mother' products is not in your product feed (as required by Google).";
1445
+ break;
1446
+ case "g:shipping";
1447
+ $helptext = "(Required when you need to override the shipping settings that you set up in Merchant Center) Google recommends that you set up shipping costs through your Merchant center. However, when you need to override these settings you can map the g:shipping field to the 'Shipping price' attribute.";
1448
+ break;
1449
+ case "Grant access";
1450
+ $helptext = "Grant access to our support employees so we can help you out with creating your product feed.";
1451
+ break;
1452
+ case "Structured data fix";
1453
+ $helptext = "Because of a bug in WooCommerce variable products will get disapproved in Google's Merchant Center. WooCommerce adds the price of the cheapest variable product in the structured data for all variations of a product. Because of this there will be a mismatch between the product price you provide to Google in your Google Shopping product feed and the structured data price on the product landingpage. Google will therefor disapprove the product in its merchant center. You won't be able to advertise on that product in your Google Shopping campaign. Enable this option will fix the structured data on variable product pages by adding the correct variable product price in the JSON-LD structured data so Google will approve the variable products you submitted.";
1454
+ break;
1455
+ case "Unique identifiers";
1456
+ $helptext = "In order to optimise your product feed for Google Shopping and meet all Google's Merchant Center requirements you need to add extra fields / attributes to your products that are not part of WooCommerce by default. Enable this option to get Brand, GTIN, MPN, UPC, EAN, Product condition and optimised title fields";
1457
+ break;
1458
+ default:
1459
+ $helptext = "need information about this field? reach out to support@adtribes.io";
1460
+ }
1461
+
1462
+ $data = array (
1463
+ 'helptext' => $helptext,
1464
+ );
1465
+
1466
+ echo json_encode($data);
1467
+ wp_die();
1468
+ }
1469
+ add_action( 'wp_ajax_woosea_fieldmapping_dialog_helptext', 'woosea_fieldmapping_dialog_helptext' );
1470
+
1471
+
1472
  /**
1473
  * Get the dropdowns for the fieldmapping page
1474
  */
1710
  }
1711
 
1712
  /**
1713
+ * Check for active license, is this a paid version of the plugin?
1714
  * This function is called by the cron after 30 seconds. The check only
1715
  * needs to be done once and not continuesly so it gets removed.
1716
  */
1720
  }
1721
  add_action( 'woosea_deregister_hook', 'woosea_de_register_license', 99999); // deregister the paid version check after 60 seconds
1722
 
1723
+ /**
1724
+ * This function checks if the Elite license is valid. When the license
1725
+ * key is invalid or expired the advanced options of this plugin will be disabled
1726
+ */
1727
+ function woosea_license_valid(){
1728
+ $domain = $_SERVER['HTTP_HOST'];
1729
+ $license_information = get_option('license_information');
1730
+
1731
+ $curl = curl_init();
1732
+ $url = "https://www.adtribes.io/check/license.php?key=$license_information[license_key]&email=$license_information[license_email]&domain=$domain&version=3.0.0";
1733
+
1734
+ curl_setopt_array($curl, array(
1735
+ CURLOPT_RETURNTRANSFER => 1,
1736
+ CURLOPT_URL => $url,
1737
+ CURLOPT_USERAGENT => 'AdTribes license cURL Request'
1738
+ ));
1739
+ $response = curl_exec( $curl );
1740
+ curl_close($curl);
1741
+ $json_return = json_decode($response, true);
1742
+
1743
+ $license_start_time = strtotime($json_return['created']);
1744
+ $license_end_time = strtotime('+1 years', $license_start_time);
1745
+ $current_time = time();
1746
+ $license_information['notice'] = $json_return['notice'];
1747
+
1748
+ if($json_return['valid'] == "false"){
1749
+ $license_information['message'] = $json_return['message'];
1750
+ $license_information['message_type'] = $json_return['message_type'];
1751
+ $license_information['license_valid'] = "false";
1752
+ $license_information['license_key'] = $json_return['license_key'];
1753
+ $license_information['license_email'] = $json_return['license_email'];
1754
+
1755
+ update_option ('license_information', $license_information);
1756
+ delete_option ('structured_data_fix');
1757
+ delete_option ('add_unique_identifiers');
1758
+ } else {
1759
+ $license_information['message'] = $json_return['message'];
1760
+ $license_information['message_type'] = $json_return['message_type'];
1761
+ $license_information['license_valid'] = "true";
1762
+
1763
+ update_option ('license_information', $license_information);
1764
+ }
1765
+ }
1766
+
1767
+
1768
  /**
1769
  * Function used by event scheduling to create feeds
1770
  * Feed can automatically be generated every hour, twicedaiy or once a day
1771
  */
1772
  function woosea_create_all_feeds(){
1773
+ $feed_config = array();
1774
  $feed_config = get_option( 'cron_projects' );
1775
  $nr_projects = count($feed_config);
1776
  $cron_start_date = date("d M Y H:i");
1818
  } else {
1819
  $start_project = woosea_continue_batch($val['project_hash']);
1820
  }
1821
+ unset($start_project);
1822
+ } elseif (($val['cron'] == "no refresh") AND ($hour == 26)){
1823
+ // It is never hour 26, so this project will never refresh
1824
  } elseif ($val['cron'] == "hourly") {
1825
  $batch_project = "batch_project_".$val['project_hash'];
1826
  if (!get_option( $batch_project )){
1907
 
1908
  if($save_conversion == "yes"){
1909
  list($project_hash, $plugin, $productId) = explode('|', $adTribesID);
1910
+
1911
+ if((!empty($productId)) AND ($productId > 0)){
1912
+ $conversion_timestamp = date("j-n-Y G:i:s");
1913
+
1914
+ // Insert the conversion data into the MySql conversion table
1915
+ global $wpdb;
1916
+ $charset_collate = $wpdb->get_charset_collate();
1917
+ $table_name = $wpdb->prefix . 'adtribes_my_conversions';
1918
+
1919
+ // Get the last order ID
1920
+ $orderId = get_option( 'last_order_id' );
1921
+ $inserted_id = 0;
1922
+ $success = "no";
1923
+
1924
+ // Check if order was not inserted before inserting it.
1925
+ $orderId_check = $wpdb->get_results("SELECT * FROM $table_name WHERE orderId = '".$orderId."'");
1926
+
1927
+ if($wpdb->num_rows == 0){
1928
+ $wpdb->insert($table_name,
1929
+ array(
1930
+ 'conversion_time' => current_time('mysql' , 1),
1931
+ 'project_hash' => $project_hash,
1932
+ 'utm_source' => $utm_source,
1933
+ 'utm_campaign' => $utm_campaign,
1934
+ 'utm_medium' => $utm_medium,
1935
+ 'utm_term' => $utm_term,
1936
+ 'productId' => $productId,
1937
+ 'orderId' => $orderId
1938
+ ),
1939
+ array(
1940
+ '%s',
1941
+ '%s',
1942
+ '%s',
1943
+ '%s',
1944
+ '%s',
1945
+ '%s',
1946
+ '%d',
1947
+ '%d'
1948
+ )
1949
+ );
1950
+
1951
+ $inserted_id = $wpdb->insert_id;
1952
+ }
1953
 
1954
+ if($inserted_id > 0){
1955
+ $success = "yes";
1956
+ }
1957
 
1958
+ $data = array (
1959
+ "conversion_saved" => $success,
1960
+ );
1961
 
1962
+ $data = json_encode($data);
1963
+ echo $data;
1964
+ wp_die();
1965
+ }
1966
  }
1967
  }
1968
  add_action( 'wp_ajax_woosea_track_conversion','woosea_track_conversion');
2032
  echo $html->get_page();
2033
  }
2034
 
2035
+ /**
2036
+ * Function with initialisation of class for the upgrade to Elite page
2037
+ */
2038
+ function woosea_upgrade_elite(){
2039
+ $html = new Construct_Admin_Pages();
2040
+ $html->set_page("woosea-upgrade-elite");
2041
+ echo $html->get_page();
2042
+ }
2043
+
2044
  /**
2045
  * Function for emptying all projects in cron at once
2046
  * Kill-switch for all configured projects, be carefull!