Ecwid Ecommerce Shopping Cart - Version 6.11

Version Description

  • Nov 29, 2022 =
  • New cool feature speedup of storefront loading. We drastically improved the load speed of Ecwid stores published on WordPress. We optimized the resources loaded by the plugin to accelerate the loading of store pages and ecommerce widgets (shopping cart icon, product search, etc). The improvement greatly enhances the user experience and boosts your store SEO. You will now get better performance scores when checking your store pages in Google PageSpeed Insights. In the coming weeks, we will gradually enable this feature for all of our users.
Download this release

Release Info

Developer Ecwid
Plugin Icon 128x128 Ecwid Ecommerce Shopping Cart
Version 6.11
Comparing to
See all releases

Code changes from version 6.10.29 to 6.11

Files changed (39) hide show
  1. css/frontend.css +35 -31
  2. css/themes/twentytwenty.css +5 -4
  3. css/themes/twentytwentyone.css +5 -4
  4. css/themes/twentytwentythree.css +2 -2
  5. css/themes/twentytwentytwo.css +5 -4
  6. ecwid-shopping-cart.php +265 -328
  7. includes/class-ec-store-defer-init.php +151 -0
  8. includes/class-ecwid-ajax-defer-renderer.php +3 -11
  9. includes/class-ecwid-html-meta.php +7 -5
  10. includes/class-ecwid-nav-menus.php +1 -1
  11. includes/class-ecwid-products.php +1 -0
  12. includes/class-ecwid-seo-links.php +1 -1
  13. includes/class-ecwid-static-page.php +80 -58
  14. includes/gutenberg/class-ecwid-gutenberg-block-minicart.php +9 -9
  15. includes/integrations/class-ecwid-integration-above-the-fold.php +0 -20
  16. includes/integrations/class-ecwid-integration-autoptimize.php +11 -15
  17. includes/shortcodes/class-ecwid-shortcode-base.php +8 -4
  18. includes/shortcodes/class-ecwid-shortcode-minicart.php +1 -1
  19. includes/shortcodes/class-ecwid-shortcode-productbrowser.php +79 -30
  20. includes/widgets.php +8 -1
  21. includes/widgets/class-ecwid-widget-base.php +9 -2
  22. includes/widgets/class-ecwid-widget-floating-shopping-cart.php +5 -2
  23. includes/widgets/class-ecwid-widget-latest-products.php +11 -10
  24. includes/widgets/class-ecwid-widget-minicart-miniview.php +7 -13
  25. includes/widgets/class-ecwid-widget-minicart.php +7 -13
  26. includes/widgets/class-ecwid-widget-products-base.php +6 -5
  27. includes/widgets/class-ecwid-widget-random-product.php +17 -16
  28. includes/widgets/class-ecwid-widget-random-products.php +0 -58
  29. includes/widgets/class-ecwid-widget-search.php +9 -10
  30. includes/widgets/class-ecwid-widget-store-link.php +5 -5
  31. includes/widgets/class-ecwid-widget-vcategories.php +1 -5
  32. includes/widgets/nsf-minicart.tpl.php +2 -2
  33. js/cache-control.js +0 -23
  34. js/defer-actions.js +21 -0
  35. js/frontend.js +15 -9
  36. js/static-page.js +230 -49
  37. lib/ecwid_platform.php +11 -8
  38. readme.txt +4 -1
  39. templates/shortcode-pb-placeholder.php +212 -0
css/frontend.css CHANGED
@@ -1,102 +1,106 @@
1
  html#ecwid_html body#ecwid_body .ecwid.ecwid-SingleProduct a,
2
  .ecwid-SingleProduct a div.ecwid-title {
3
- color: #000;
4
- text-decoration: none;
5
  }
6
 
7
  html#ecwid_html body#ecwid_body .ecwid-SearchPanel input {
8
- max-width: 300px;
9
  }
10
 
11
  html#ecwid_html body#ecwid_body .ecwid-shopping-cart-categories #horizontal-menu,
12
  html#ecwid_html body#ecwid_body .ecwid-shopping-cart-categories .horizontal-menu {
13
- margin-bottom: 10px;
14
- margin-top: 10px;
15
  }
16
 
17
  .ecwid-shopping-cart-categories .horizontal-menu-item {
18
- background-image: none;
19
  }
20
 
21
  html#ecwid_html body#ecwid_body .ecwid-productsList ul li .ecwid-productsList-name {
22
- color: inherit;
23
- font-size: inherit;
24
  }
25
 
26
  html#ecwid_html body#ecwid_body .ecwid tr:hover td {
27
- color: inherit;
28
  }
29
 
30
  html#ecwid_html body#ecwid_body .ecwid table {
31
- line-height: inherit;
32
  }
33
 
34
  .ecwid-SingleProduct-v2 {
35
- box-sizing: content-box;
36
  }
37
 
38
  .ecwid .ecwid-productBrowser input {
39
- display: inline-block;
40
  }
41
 
42
  .ecwid .ecwid-productBrowser label {
43
- vertical-align: middle;
44
  }
45
 
46
  .ecwid .ecwid-productBrowser select,
47
  .ecwid .ecwid-productBrowser input {
48
- background-color: #fff;
49
- color: #333;
50
  }
51
 
52
  /* fix old search widget */
53
  .ecwid-shopping-cart-search .ecwid-SearchPanel .ecwid-SearchPanel-field {
54
- display: inline-block;
55
  }
 
56
  .ecwid-shopping-cart-search .ecwid-SearchPanel .ecwid-SearchPanel-field {
57
- font-size: 14px;
58
  }
 
59
  .ecwid-shopping-cart-search .ecwid-SearchPanel .ecwid-SearchPanel-button {
60
- font-size: 14px;
61
- font-weight: 400;
62
  }
63
 
64
 
65
  html#ecwid_html body#ecwid_body .ecwid.ecwid-SingleProduct-v2.ecwid-random-product {
66
- min-width: unset;
67
  }
68
 
69
  .ecwid-random-product:not(.loaded) {
70
- min-height: 290px;
71
  }
72
 
73
  .ecwid-shopping-cart-categories {
74
- min-height: 51px;
75
- margin: 10px 0;
76
  }
77
 
78
  .ecwid-shopping-cart-search {
79
- min-height: 42px;
80
  }
81
 
82
- #dynamic-ec-store {
83
- width: 100%;
84
  }
 
85
  .hide-ec-dynamic-placeholder {
86
- margin-bottom: 0 !important;
87
  }
 
88
  .hide-ec-dynamic-placeholder .ecwid-shopping-cart-product-browser {
89
- display: none;
90
  }
91
 
92
  .ec-demo-notice {
93
- text-align: center;
94
  }
95
 
96
  .ec-demo-notice .ec-notice__wrap {
97
- background-color:#fcf5e8 !important;
98
  }
99
 
100
  .ec-cart-widget[data-icon]::before {
101
- content: '';
102
  }
1
  html#ecwid_html body#ecwid_body .ecwid.ecwid-SingleProduct a,
2
  .ecwid-SingleProduct a div.ecwid-title {
3
+ color: #000;
4
+ text-decoration: none;
5
  }
6
 
7
  html#ecwid_html body#ecwid_body .ecwid-SearchPanel input {
8
+ max-width: 300px;
9
  }
10
 
11
  html#ecwid_html body#ecwid_body .ecwid-shopping-cart-categories #horizontal-menu,
12
  html#ecwid_html body#ecwid_body .ecwid-shopping-cart-categories .horizontal-menu {
13
+ margin-bottom: 10px;
14
+ margin-top: 10px;
15
  }
16
 
17
  .ecwid-shopping-cart-categories .horizontal-menu-item {
18
+ background-image: none;
19
  }
20
 
21
  html#ecwid_html body#ecwid_body .ecwid-productsList ul li .ecwid-productsList-name {
22
+ color: inherit;
23
+ font-size: inherit;
24
  }
25
 
26
  html#ecwid_html body#ecwid_body .ecwid tr:hover td {
27
+ color: inherit;
28
  }
29
 
30
  html#ecwid_html body#ecwid_body .ecwid table {
31
+ line-height: inherit;
32
  }
33
 
34
  .ecwid-SingleProduct-v2 {
35
+ box-sizing: content-box;
36
  }
37
 
38
  .ecwid .ecwid-productBrowser input {
39
+ display: inline-block;
40
  }
41
 
42
  .ecwid .ecwid-productBrowser label {
43
+ vertical-align: middle;
44
  }
45
 
46
  .ecwid .ecwid-productBrowser select,
47
  .ecwid .ecwid-productBrowser input {
48
+ background-color: #fff;
49
+ color: #333;
50
  }
51
 
52
  /* fix old search widget */
53
  .ecwid-shopping-cart-search .ecwid-SearchPanel .ecwid-SearchPanel-field {
54
+ display: inline-block;
55
  }
56
+
57
  .ecwid-shopping-cart-search .ecwid-SearchPanel .ecwid-SearchPanel-field {
58
+ font-size: 14px;
59
  }
60
+
61
  .ecwid-shopping-cart-search .ecwid-SearchPanel .ecwid-SearchPanel-button {
62
+ font-size: 14px;
63
+ font-weight: 400;
64
  }
65
 
66
 
67
  html#ecwid_html body#ecwid_body .ecwid.ecwid-SingleProduct-v2.ecwid-random-product {
68
+ min-width: unset;
69
  }
70
 
71
  .ecwid-random-product:not(.loaded) {
72
+ min-height: 290px;
73
  }
74
 
75
  .ecwid-shopping-cart-categories {
76
+ min-height: 51px;
77
+ margin: 10px 0;
78
  }
79
 
80
  .ecwid-shopping-cart-search {
81
+ min-height: 42px;
82
  }
83
 
84
+ #dynamic-ec-store-container {
85
+ width: 100%;
86
  }
87
+
88
  .hide-ec-dynamic-placeholder {
89
+ margin-bottom: 0 !important;
90
  }
91
+
92
  .hide-ec-dynamic-placeholder .ecwid-shopping-cart-product-browser {
93
+ display: none;
94
  }
95
 
96
  .ec-demo-notice {
97
+ text-align: center;
98
  }
99
 
100
  .ec-demo-notice .ec-notice__wrap {
101
+ background-color: #fcf5e8 !important;
102
  }
103
 
104
  .ec-cart-widget[data-icon]::before {
105
+ content: '';
106
  }
css/themes/twentytwenty.css CHANGED
@@ -1,7 +1,8 @@
1
- #dynamic-ec-store, #static-ec-store {
2
- max-width: 120rem;
 
3
  }
4
 
5
- #ecwid_body .entry-content > [data-elementor-type] {
6
- max-width: 120rem !important;
7
  }
1
+ #dynamic-ec-store-container,
2
+ #static-ec-store-container {
3
+ max-width: 120rem;
4
  }
5
 
6
+ #ecwid_body .entry-content>[data-elementor-type] {
7
+ max-width: 120rem !important;
8
  }
css/themes/twentytwentyone.css CHANGED
@@ -1,7 +1,8 @@
1
- #dynamic-ec-store, #static-ec-store {
2
- max-width: 80rem;
 
3
  }
4
 
5
  #ecwid_body .vc_row {
6
- max-width: 80rem;
7
- }
1
+ #dynamic-ec-store-container,
2
+ #static-ec-store-container {
3
+ max-width: 80rem;
4
  }
5
 
6
  #ecwid_body .vc_row {
7
+ max-width: 80rem;
8
+ }
css/themes/twentytwentythree.css CHANGED
@@ -1,5 +1,5 @@
1
- #dynamic-ec-store,
2
- #static-ec-store,
3
  #ecwid_html .wp-block-post-title,
4
  #ecwid_body .wp-block-post-title {
5
  max-width: 1200px;
1
+ #dynamic-ec-store-container,
2
+ #static-ec-store-container,
3
  #ecwid_html .wp-block-post-title,
4
  #ecwid_body .wp-block-post-title {
5
  max-width: 1200px;
css/themes/twentytwentytwo.css CHANGED
@@ -1,7 +1,8 @@
1
- #dynamic-ec-store, #static-ec-store {
2
- max-width: 1000px;
 
3
  }
4
 
5
  #ecwid_body .vc_row {
6
- max-width: 1000px;
7
- }
1
+ #dynamic-ec-store-container,
2
+ #static-ec-store-container {
3
+ max-width: 1000px;
4
  }
5
 
6
  #ecwid_body .vc_row {
7
+ max-width: 1000px;
8
+ }
ecwid-shopping-cart.php CHANGED
@@ -5,7 +5,7 @@ Plugin URI: http://www.ecwid.com?partner=wporg
5
  Description: Ecwid is a free full-featured shopping cart. It can be easily integrated with any Wordpress blog and takes less than 5 minutes to set up.
6
  Text Domain: ecwid-shopping-cart
7
  Author: Ecwid Ecommerce
8
- Version: 6.10.29
9
  Author URI: https://ecwid.to/ecwid-site
10
  License: GPLv2 or later
11
  */
@@ -46,7 +46,7 @@ if ( is_admin() ) {
46
 
47
  add_action( 'admin_init', 'ecwid_settings_api_init' );
48
  add_action( 'admin_init', 'ecwid_check_version' );
49
- add_action( 'wp_ajax_check_api_cache', 'ecwid_admin_check_api_cache' );
50
 
51
  add_action( 'admin_enqueue_scripts', 'ecwid_common_admin_scripts' );
52
  add_action( 'admin_enqueue_scripts', 'ecwid_register_admin_styles' );
@@ -76,7 +76,8 @@ if ( is_admin() ) {
76
  add_action( 'init', 'ecwid_check_api_cache' );
77
 
78
  add_action( 'template_redirect', 'ecwid_404_on_broken_escaped_fragment' );
79
- add_action( 'template_redirect', 'ecwid_apply_theme' ); // Why not init?
 
80
 
81
  add_action( 'wp', 'ecwid_seo_ultimate_compatibility', 0 );
82
  add_action( 'wp', 'ecwid_remove_default_canonical' );
@@ -90,7 +91,6 @@ if ( is_admin() ) {
90
  add_action( 'wp_enqueue_scripts', 'ecwid_enqueue_frontend' );
91
  add_filter( 'wp_title', 'ecwid_seo_title', 10000, 3 );
92
  add_filter( 'document_title_parts', 'ecwid_seo_title_parts' );
93
- add_action( 'plugins_loaded', 'ecwid_minifier_compatibility', 0 );
94
  add_filter( 'widget_meta_poweredby', 'ecwid_add_credits' );
95
  add_filter( 'body_class', 'ecwid_body_class' );
96
  add_action( 'redirect_canonical', 'ecwid_redirect_canonical', 10, 2 );
@@ -134,13 +134,13 @@ if ( is_admin() ) {
134
 
135
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-nav-menus.php';
136
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-ajax-defer-renderer.php';
 
137
 
138
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-store-page.php';
139
 
140
  require_once ECWID_PLUGIN_DIR . 'lib/ecwid_product.php';
141
  require_once ECWID_PLUGIN_DIR . 'lib/ecwid_category.php';
142
 
143
-
144
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-seo-links.php';
145
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-html-meta.php';
146
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-wp-dashboard-feed.php';
@@ -161,11 +161,11 @@ if ( version_compare( $version, '4.0' ) >= 0 ) {
161
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-floating-minicart.php';
162
  }
163
 
164
- if ( strpos( $version, '5.0' ) === 0 || version_compare( $version, '5.0' ) > 0 ) {
165
  require_once ECWID_PLUGIN_DIR . 'includes/gutenberg/class-ecwid-gutenberg.php';
166
  }
167
 
168
- if ( strpos( $version, '5.5' ) === 0 || version_compare( $version, '5.5' ) >= 0 ) {
169
  require_once ECWID_PLUGIN_DIR . 'includes/class-ec-store-sitemap-provider.php';
170
  }
171
 
@@ -195,7 +195,6 @@ function ecwid_init_integrations() {
195
  'wordpress-seo-premium/wp-seo-premium.php' => 'wpseo',
196
  'divi-builder/divi-builder.php' => 'divibuilder',
197
  'autoptimize/autoptimize.php' => 'autoptimize',
198
- 'above-the-fold-optimization/abovethefold.php' => 'above-the-fold',
199
  'js_composer/js_composer.php' => 'wpbakery-composer',
200
  'beaver-builder-lite-version/fl-builder.php' => 'beaver-builder',
201
  'bb-plugin/fl-builder.php' => 'beaver-builder',
@@ -251,14 +250,14 @@ if ( version_compare( $version, '3.6' ) < 0 ) {
251
  * http://core.trac.wordpress.org/browser/tags/3.6/wp-includes/shortcodes.php
252
  */
253
 
254
- if (!function_exists('shortcode_exists')) {
255
  function shortcode_exists( $tag ) {
256
  global $shortcode_tags;
257
  return array_key_exists( $tag, $shortcode_tags );
258
  }
259
  }
260
 
261
- if (!function_exists('has_shortcode')) {
262
  function has_shortcode( $content, $tag ) {
263
  if ( false === strpos( $content, '[' ) ) {
264
  return false;
@@ -283,18 +282,17 @@ if ( version_compare( $version, '3.6' ) < 0 ) {
283
  }
284
 
285
  if ( is_admin() ) {
286
- $main_button_class = "";
287
- if ( version_compare($version, '3.8-beta' ) > 0) {
288
- $main_button_class = "button-primary";
289
  } else {
290
- $main_button_class = "pure-button pure-button-primary";
291
  }
292
 
293
- define('ECWID_MAIN_BUTTON_CLASS', $main_button_class);
294
  }
295
 
296
- function ecwid_body_class($classes)
297
- {
298
  if ( Ecwid_Store_Page::is_store_page() ) {
299
  $classes[] = 'ecwid-shopping-cart';
300
  }
@@ -302,24 +300,24 @@ function ecwid_body_class($classes)
302
  return $classes;
303
  }
304
 
305
- function ecwid_redirect_canonical($redirect_url, $requested_url) {
306
- if (!is_front_page()) {
307
  return $redirect_url;
308
  }
309
 
310
- if (strpos($requested_url, '_escaped_fragment_') === false) {
311
  return $redirect_url;
312
  }
313
 
314
- $parsed = parse_url($requested_url);
315
  $query = array();
316
- parse_str($parsed['query'], $query);
317
 
318
- if (!array_key_exists('_escaped_fragment_', $query)) {
319
  return $redirect_url;
320
  }
321
 
322
- if (! Ecwid_Store_Page::is_store_page() ) {
323
  return $redirect_url;
324
  }
325
 
@@ -356,18 +354,18 @@ function ecwid_maybe_remove_emoji() {
356
  }
357
  }
358
 
359
- add_action('wp_ajax_ecwid_get_product_info', 'ecwid_ajax_get_product_info' );
360
- add_action('wp_ajax_nopriv_ecwid_get_product_info', 'ecwid_ajax_get_product_info' );
361
 
362
- add_filter('redirect_canonical', 'ecwid_redirect_canonical2', 10, 3);
363
 
364
- function ecwid_redirect_canonical2($redir, $req) {
365
  global $wp_query;
366
 
367
  $adds_slash = $req . '/' == $redir;
368
- $adds_slash |= urldecode($req . '/') == urldecode($redir);
369
-
370
- if (Ecwid_Store_Page::is_store_page() && $adds_slash) {
371
  return $req;
372
  }
373
 
@@ -376,14 +374,13 @@ function ecwid_redirect_canonical2($redir, $req) {
376
 
377
  add_action( 'current_screen', 'ecwid_add_deactivation_popup' );
378
 
379
- function ecwid_add_deactivation_popup()
380
- {
381
  if ( get_current_screen()->id == 'plugins' ) {
382
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-popup-deactivate.php';
383
-
384
  $popup = new Ecwid_Popup_Deactivate();
385
-
386
- if ( !$popup->is_disabled() ) {
387
  Ecwid_Popup::add_popup( $popup );
388
  }
389
  }
@@ -391,28 +388,28 @@ function ecwid_add_deactivation_popup()
391
 
392
  function ecwid_enqueue_frontend() {
393
  global $ecwid_current_theme;
394
-
395
- if ( $ecwid_current_theme && $ecwid_current_theme->historyjs_html4mode || get_option('ecwid_historyjs_html4mode') ) {
396
  wp_enqueue_script('ecwid-historyjs-wa', ECWID_PLUGIN_URL . 'js/historywa.js');
397
  }
398
 
399
- $version = get_bloginfo('version');
400
- if ( !wp_script_is('jquery-ui-widget') && version_compare($version, '5.6') < 0 ) {
401
- wp_enqueue_script('jquery-ui-widget', includes_url() . 'js/jquery/ui/widget.min.js', array('jquery'));
402
  }
403
 
404
- wp_enqueue_style('ecwid-css', ECWID_PLUGIN_URL . 'css/frontend.css',array(), get_option('ecwid_plugin_version'));
405
-
406
- wp_enqueue_script( 'ecwid-frontend-js', ECWID_PLUGIN_URL . 'js/frontend.js', array( 'jquery' ), get_option( 'ecwid_plugin_version' ) );
407
  wp_localize_script( 'ecwid-frontend-js', 'ecwidParams', array(
408
  'useJsApiToOpenStoreCategoriesPages' => Ecwid_Nav_Menus::should_use_js_api_for_categories_menu(),
409
  'storeId' => get_ecwid_store_id()
410
  ));
411
-
412
  if ( get_post() && get_post()->post_type == Ecwid_Products::POST_TYPE_PRODUCT ) {
413
  wp_enqueue_script( 'ecwid-post-product', ECWID_PLUGIN_URL . 'js/post-product.js', array(), get_option( 'ecwid_plugin_version' ), TRUE );
414
 
415
- $meta = get_post_meta(get_the_ID(), 'ecwid_id');
416
 
417
  wp_localize_script( 'ecwid-post-product', 'ecwidPost', array(
418
  'productId' => $meta[0],
@@ -420,8 +417,8 @@ function ecwid_enqueue_frontend() {
420
  ) );
421
  }
422
 
423
- if (is_active_widget(false, false, 'ecwidrecentlyviewed')) {
424
- wp_enqueue_script('ecwid-recently-viewed', ECWID_PLUGIN_URL . 'js/recently-viewed-common.js', array('jquery', 'utils'), get_option('ecwid_plugin_version'), true);
425
 
426
  wp_localize_script(
427
  'ecwid-products-list-js',
@@ -433,32 +430,32 @@ function ecwid_enqueue_frontend() {
433
  );
434
  }
435
 
436
- if (is_plugin_active('contact-form-7-designer/cf7-styles.php')) {
437
- wp_enqueue_script('ecwid-cf7designer', ECWID_PLUGIN_URL . 'js/cf7designer.js', array(), get_option('ecwid-plugin-version'), true);
438
  }
439
 
440
- if (current_user_can('manage_options')) {
441
- wp_enqueue_style('ecwid-fonts-css', ECWID_PLUGIN_URL . 'css/fonts.css', array(), get_option('ecwid_plugin_version'));
442
  }
443
 
444
  if ( Ecwid_Store_Page::is_store_page() && ( current_user_can( Ecwid_Admin::get_capability() ) || is_admin_bar_showing() ) ) {
445
  $is_post_edit_replace = true;
446
 
447
- if( Ecwid_Config::is_wl() && !Ecwid_Api_V3::is_available() ) {
448
  $is_post_edit_replace = false;
449
  }
450
-
451
- if( $is_post_edit_replace ) {
452
 
453
  $post_edit_url = 'https://my.ecwid.com/#';
454
  $is_api_available = false;
455
 
456
- if( Ecwid_Config::is_wl() || Ecwid_Api_V3::is_available() ) {
457
  $post_edit_url = get_admin_url() . 'admin.php?page=ec-store&ec-store-page=';
458
  $is_api_available = true;
459
  }
460
 
461
- if( !ecwid_is_demo_store() ) {
462
  wp_enqueue_script( 'ecwid-admin-bar-js', ECWID_PLUGIN_URL . 'js/admin-bar.js', array( 'jquery' ), get_option( 'ecwid_plugin_version' ) );
463
  wp_localize_script( 'ecwid-admin-bar-js', 'ecwidEditPostLinkParams', array(
464
  'languages' => array(
@@ -502,14 +499,14 @@ add_action( 'ecwid_inline_js_config', 'ecwid_add_chameleon' );
502
  function ecwid_add_chameleon( $js ) {
503
 
504
  $colors = array();
505
- foreach (array('foreground', 'background', 'link', 'price', 'button') as $kind) {
506
  $color = get_option( 'ecwid_chameleon_colors_' . $kind );
507
  if ( $color ) {
508
- $colors['color-' . $kind] = $color;
509
  }
510
  }
511
 
512
- if ( !get_option( 'ecwid_use_chameleon' ) && empty( $colors ) ) {
513
  return $js;
514
  }
515
 
@@ -517,23 +514,23 @@ function ecwid_add_chameleon( $js ) {
517
  $colors = 'auto';
518
  }
519
 
520
- $colors = json_encode($colors);
521
  $font = '"auto"';
522
 
523
  $chameleon = apply_filters( 'ecwid_chameleon_settings', array( 'colors' => $colors, 'font' => $font ) );
524
 
525
- if ( !is_array($chameleon) ) {
526
  $chameleon = array(
527
  'colors' => $colors,
528
- 'font' => $font
529
  );
530
  }
531
 
532
- if ( !isset( $chameleon['colors'] ) ) {
533
- $chameleon['colors'] = json_encode($colors);
534
  }
535
 
536
- if ( !isset( $chameleon['font'] ) ) {
537
  $chameleon['font'] = $font;
538
  }
539
 
@@ -656,73 +653,72 @@ function ecwid_minifier_compatibility()
656
  }
657
  }
658
 
659
- function ecwid_check_version()
660
- {
661
- $plugin_data = get_plugin_data(__FILE__);
662
  $current_version = $plugin_data['Version'];
663
- $stored_version = get_option('ecwid_plugin_version', null);
664
 
665
- $migration_since_version = get_option('ecwid_plugin_migration_since_version', null);
666
- if (is_null($migration_since_version)) {
667
- update_option('ecwid_plugin_migration_since_version', $current_version);
668
  }
669
 
670
- $fresh_install = !$stored_version;
671
- $upgrade = $stored_version && version_compare($current_version, $stored_version) > 0;
672
 
673
- if ($fresh_install) {
 
 
 
674
 
675
- do_action('ecwid_plugin_installed', $current_version);
676
- add_option('ecwid_plugin_version', $current_version);
677
-
678
  // Called in Ecwid_Seo_Links->on_fresh_install
679
  do_action( 'ecwid_on_fresh_install' );
680
 
681
- } elseif ($upgrade) {
 
 
 
682
 
683
- do_action('ecwid_plugin_upgraded', array( 'old' => $stored_version, 'new' => $current_version ) );
684
- update_option('ecwid_plugin_version', $current_version);
685
-
686
  do_action( 'ecwid_on_plugin_upgrade' );
687
- }
688
 
689
- if ($fresh_install || $upgrade || isset($_GET['ecwid_reinit'])) {
690
 
691
  add_option( Ecwid_Seo_Links::OPTION_ENABLED, false );
692
 
693
- if (ecwid_migrations_is_original_plugin_version_older_than('4.3')) {
694
- add_option('ecwid_fetch_url_use_file_get_contents', '');
695
- add_option('ecwid_remote_get_timeout', '5');
696
  }
697
 
698
  add_option( 'ecwid_support_email', 'wordpress@ecwid.com' );
699
 
700
- add_option('ecwid_enable_sso');
701
 
702
  add_option( Ecwid_Products::OPTION_ENABLED, Ecwid_Products::is_enabled() );
703
 
704
- add_option('ecwid_disable_pb_url', false );
705
- add_option('ecwid_historyjs_html4mode', false);
706
 
707
- add_option(Ecwid_Widget_Floating_Shopping_Cart::OPTION_DISPLAY_POSITION, '');
708
 
709
  // Since 5.4
710
- delete_option('ecwid_use_new_search');
711
- delete_option('ecwid_use_new_categories');
712
  // /Since 5.4
713
 
714
  // Since 5.4.2
715
- delete_option('ecwid_hide_appearance_menu');
716
-
717
- // Since 5.4.3
718
  add_option( Ecwid_Widget_Floating_Shopping_Cart::OPTION_MOVE_INTO_BODY, '' );
719
-
720
  // Since 5.7.3
721
  delete_option( 'ecwid_use_js_api_to_open_store_pages' );
722
 
723
- // Since 5.7.4
724
  update_option( 'ecwid_use_js_api_to_open_store_categories_pages', Ecwid_Nav_Menus::OPTVAL_USE_JS_API_FOR_CATS_MENU_AUTO );
725
-
726
  // Since 5.8
727
  add_option( Ecwid_Admin::OPTION_ENABLE_AUTO_MENUS, 'auto' );
728
 
@@ -731,50 +727,50 @@ function ecwid_check_version()
731
 
732
  // Since 5.8.1+
733
  add_option( Ecwid_Products::OPTION_SYNC_LIMIT, 20 );
734
-
735
  // Since 6.0.x
736
  add_option( 'ecwid_hide_prefetch', 'off' );
737
 
738
- // Since 6.1.x
739
  if ( class_exists( 'Ecwid_Floating_Minicart' ) ) {
740
  Ecwid_Floating_Minicart::create_default_options();
741
  }
742
  add_option( 'ecwid_hide_old_minicart', ecwid_is_recent_installation() );
743
-
744
  Ecwid_Config::load_from_ini();
745
 
746
  // Since 6.2.x
747
  delete_option( 'force_scriptjs_render' );
748
-
749
  // Since 6.4.x
750
  add_option( EcwidPlatform::OPTION_LOG_CACHE );
751
-
752
  // Since 6.4.8
753
  add_option( 'ecwid_hide_canonical', false );
754
 
755
  // Since 6.4.9
756
  add_option( Ecwid_Theme_Base::OPTION_LEGACY_CUSTOM_SCROLLER, false );
757
-
758
  // Since 6.4.9+
759
  add_option( 'ecwid_remove_emoji', 'Y' );
760
 
761
  // Since 6.4.14+
762
  add_option( Ecwid_Store_Page::OPTION_REPLACE_TITLE, $fresh_install ? 'Y' : '' );
763
-
764
  do_action( 'ecwid_on_plugin_update' );
765
 
766
- Ecwid_Store_Page::add_store_page( get_option('ecwid_store_page_id') );
767
- Ecwid_Store_Page::add_store_page( get_option('ecwid_store_page_id_auto') );
768
 
769
- if (Ecwid_Store_Page::get_current_store_page_id()) {
770
- delete_option('ecwid_store_page_id_auto');
771
  }
772
 
773
  Ecwid_Api_V3::reset_api_status();
774
  flush_rewrite_rules();
775
- }
776
-
777
- add_option('ecwid_disable_dashboard', '');
778
  }
779
 
780
  function ecwid_get_woocommerce_status() {
@@ -798,15 +794,13 @@ function ecwid_get_woocommerce_status() {
798
  return $woo;
799
  }
800
 
801
- function ecwid_is_recent_installation()
802
- {
803
- return get_option( 'ecwid_plugin_migration_since_version' ) == get_option('ecwid_plugin_version' );
804
  }
805
 
806
- function ecwid_migrations_is_original_plugin_version_older_than($version)
807
- {
808
- $migration_since_version = get_option('ecwid_plugin_migration_since_version', null);
809
- return version_compare($migration_since_version, $version) < 0;
810
  }
811
 
812
  function ecwid_log_error($message)
@@ -833,12 +827,6 @@ function ecwid_log_error($message)
833
  update_option('ecwid_error_log', json_encode($errors));
834
  }
835
 
836
- function ecwid_get_last_logged_error()
837
- {
838
- return '';
839
- }
840
-
841
-
842
  function ecwid_override_option($name, $new_value = null)
843
  {
844
  static $overridden = array();
@@ -853,9 +841,9 @@ function ecwid_override_option($name, $new_value = null)
853
  update_option($name, $overridden[$name]);
854
  }
855
  }
856
- function ecwid_tinymce_init($in)
857
- {
858
- if(!empty($in['extended_valid_elements'])) {
859
  $in['extended_valid_elements'] .= ',';
860
  } else {
861
  $in['extended_valid_elements'] = '';
@@ -866,102 +854,101 @@ function ecwid_tinymce_init($in)
866
  return $in;
867
  }
868
 
869
- function ecwid_seo_ultimate_compatibility()
870
- {
871
  global $seo_ultimate;
872
 
873
- if (!$seo_ultimate) return;
874
- if (!Ecwid_Store_Page::is_store_page()) return;
875
-
 
 
 
 
876
  if ( isset( $_GET['_escaped_fragment_'] ) || ( Ecwid_Seo_Links::is_enabled() && Ecwid_Seo_Links::is_product_browser_url() ) ) {
877
- remove_action('template_redirect', array($seo_ultimate->modules['titles'], 'before_header'), 0);
878
- remove_action('wp_head', array($seo_ultimate->modules['titles'], 'after_header'), 1000);
879
- remove_action('su_head', array($seo_ultimate->modules['meta-descriptions'], 'head_tag_output'));
880
- remove_action('su_head', array($seo_ultimate->modules['canonical'], 'link_rel_canonical_tag'));
881
- remove_action('su_head', array($seo_ultimate->modules['canonical'], 'http_link_rel_canonical'));
882
  }
883
  }
884
 
885
- function ecwid_remove_default_canonical()
886
- {
887
  if ( Ecwid_Store_Page::is_store_page() ) {
888
- remove_action( 'wp_head','rel_canonical');
889
  }
890
  }
891
 
892
- function ecwid_seo_compatibility_init($title)
893
- {
894
- if ( !array_key_exists('_escaped_fragment_', $_GET) || !Ecwid_Store_Page::is_store_page() ) {
895
- return $title;
896
- }
897
 
898
  // Platinum SEO Pack
899
- // Canonical
900
- ecwid_override_option('psp_canonical', false);
901
- // Title
902
- ecwid_override_option('aiosp_rewrite_titles', false);
903
 
904
- add_action('amt_basic_metadata_head', 'ecwid_amt_remove_description');
905
  return $title;
906
-
907
  }
908
 
909
- function ecwid_amt_remove_description($params)
910
- {
911
- foreach ($params as $key => $value) {
912
- if (preg_match('/meta name="description"/', $value)) {
913
- unset ($params[$key]);
914
  }
915
  }
916
 
917
  return $params;
918
  }
919
 
920
- function ecwid_seo_compatibility_restore()
921
- {
922
- if (!array_key_exists('_escaped_fragment_', $_GET) || !Ecwid_Store_Page::is_store_page()) {
923
- return;
924
- }
925
 
926
- ecwid_override_option('psp_canonical');
927
- ecwid_override_option('aiosp_rewrite_titles');
928
  }
929
 
930
  function ecwid_check_api_cache() {
931
  EcwidPlatform::cache_log_record( 'init', array() );
932
-
933
- $last_cache = get_option('ecwid_last_api_cache_check');
934
 
935
- if (time() - $last_cache > HOUR_IN_SECONDS ) {
 
 
936
  ecwid_invalidate_cache();
937
  }
938
  }
939
 
940
-
941
  function ecwid_enqueue_cache_control() {
942
- wp_enqueue_script('ecwid-cache-control-js', ECWID_PLUGIN_URL . 'js/cache-control.js', array(), get_option('ecwid_plugin_version'));
943
 
944
- wp_localize_script( 'ecwid-cache-control-js', 'ecwidCacheControlParams', array(
945
- 'ajax_url' => admin_url( 'admin-ajax.php' )
946
- ));
 
 
947
  }
948
 
949
- function ecwid_admin_check_api_cache()
950
- {
951
- $is_ajax_check_api_cache = isset( $_GET['action'] ) && $_GET['action'] == 'check_api_cache';
952
  $is_doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
953
- $is_get_request = isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'GET';
954
 
955
- if ( !$is_ajax_check_api_cache && ( $is_doing_ajax || $is_get_request ) ) return;
956
 
957
  EcwidPlatform::cache_log_record( 'admin_init', array() );
958
 
959
  $last_cache = get_option( 'ecwid_last_api_cache_check' );
960
 
961
- if( Ecwid_Api_V3::get_api_status() == Ecwid_Api_V3::API_STATUS_OK )
962
  $check_time_period = 5 * MINUTE_IN_SECONDS;
963
- else
964
  $check_time_period = MINUTE_IN_SECONDS;
 
965
 
966
  if ( time() - $last_cache > $check_time_period ) {
967
  Ecwid_Api_V3::reset_api_status();
@@ -970,39 +957,39 @@ function ecwid_admin_check_api_cache()
970
  ecwid_regular_cache_check();
971
  }
972
 
973
- function ecwid_invalidate_cache( $full_reset = false)
974
- {
975
  if ( $full_reset ) {
976
  ecwid_full_cache_reset();
977
  return;
978
  }
979
-
980
  ecwid_regular_cache_check();
981
  }
982
 
983
- function ecwid_regular_cache_check()
984
- {
985
  static $already_checked = false;
986
-
987
- if ( Ecwid_Api_V3::is_available() && !$already_checked ) {
988
-
989
  $already_checked = true;
990
  $api = new Ecwid_Api_V3();
991
 
992
  $stats = $api->get_store_update_stats();
993
 
994
- EcwidPlatform::cache_log_record('reg cache check', array( 'stats' => $stats ) );
995
 
996
  if ( $stats ) {
 
997
  EcwidPlatform::invalidate_products_cache_from( strtotime( $stats->productsUpdated ) );
998
  EcwidPlatform::invalidate_categories_cache_from( strtotime( $stats->categoriesUpdated ) );
999
  EcwidPlatform::invalidate_profile_cache_from( strtotime( $stats->profileUpdated ) );
1000
  update_option( 'ecwid_last_api_cache_check', time() );
 
1001
  }
1002
 
1003
- $last_transients = get_option('ecwid_last_transients_check');
1004
 
1005
- if (time() - $last_transients > MONTH_IN_SECONDS ) {
1006
  EcwidPlatform::clear_all_transients();
1007
  update_option( 'ecwid_last_transients_check', time() );
1008
  }
@@ -1010,11 +997,10 @@ function ecwid_regular_cache_check()
1010
  if ( EcwidPlatform::is_need_clear_transients() ) {
1011
  EcwidPlatform::clear_all_transients();
1012
  }
1013
- }
1014
  }
1015
 
1016
- function ecwid_full_cache_reset()
1017
- {
1018
  Ecwid_Api_V3::reset_api_status();
1019
 
1020
  EcwidPlatform::invalidate_categories_cache_from( time() );
@@ -1028,7 +1014,7 @@ function ecwid_full_cache_reset()
1028
 
1029
  $p = new Ecwid_Products();
1030
  $p->reset_dates();
1031
-
1032
  update_option( Ecwid_Api_V3::OPTION_API_STATUS, Ecwid_Api_V3::API_STATUS_OK );
1033
  update_option( 'ecwid_last_api_cache_check', time() );
1034
  }
@@ -1042,8 +1028,6 @@ function add_ecwid_admin_bar_node() {
1042
  $theme = ecwid_get_theme_name();
1043
  $store_url = Ecwid_Store_Page::get_store_url();
1044
 
1045
-
1046
- $brand = Ecwid_Config::get_brand();
1047
  if (!is_admin()) {
1048
  $subject = sprintf( __('%s plugin doesn\'t work well with my "%s" theme', 'ecwid-shopping-cart'), Ecwid_Config::get_brand(), $theme );
1049
 
@@ -1138,15 +1122,15 @@ function ecwid_content_has_productbrowser( $content ) {
1138
 
1139
  if ( class_exists( 'Ecwid_Gutenberg' ) && Ecwid_Gutenberg::content_has_productbrowser( $content ) !== false ) {
1140
  return true;
1141
- }
1142
 
1143
- $result = has_shortcode( $content, 'ecwid_productbrowser' );
1144
- if ($result) {
1145
  return $result;
1146
  }
1147
-
1148
  foreach ( Ecwid_Shortcode_Base::get_store_shortcode_names() as $shortcode_name ) {
1149
- if ( has_shortcode($content, $shortcode_name ) ) {
1150
  $shortcodes = ecwid_find_shortcodes( $content, $shortcode_name );
1151
  if ( $shortcodes ) foreach ( $shortcodes as $shortcode ) {
1152
 
@@ -1160,20 +1144,18 @@ function ecwid_content_has_productbrowser( $content ) {
1160
  }
1161
  }
1162
  }
1163
-
1164
  }
1165
 
1166
  return $result;
1167
  }
1168
 
1169
- function ecwid_get_current_user_locale()
1170
- {
1171
- if (function_exists('get_user_locale')) {
1172
  $lang = get_user_locale();
1173
  } else {
1174
  $lang = get_locale();
1175
  }
1176
-
1177
  return $lang;
1178
  }
1179
 
@@ -1197,94 +1179,88 @@ function ecwid_is_applicable_escaped_fragment() {
1197
  return true;
1198
  }
1199
 
1200
- function ecwid_trim_description($description)
1201
- {
1202
  return Ecwid_HTML_Meta::process_raw_description( $description, ECWID_TRIMMED_DESCRIPTION_LENGTH );
1203
  }
1204
 
1205
  add_action( 'wp_ajax_ecwid_deactivate_feedback', 'ecwid_ajax_deactivate_feedback' );
1206
- function ecwid_ajax_deactivate_feedback()
1207
- {
1208
- if ( ! current_user_can( Ecwid_Admin::get_capability() ) ) {
1209
- die();
1210
- }
1211
-
1212
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-popup-deactivate.php';
1213
  $popup = new Ecwid_Popup_Deactivate();
1214
  $popup->ajax_deactivate_feedback();
1215
  }
1216
 
1217
- function ecwid_ajax_hide_message($params)
1218
- {
1219
- if (!current_user_can('manage_options')) {
1220
  return;
1221
  }
1222
 
1223
- $message = isset($_GET['message']) ? sanitize_text_field(wp_unslash($_GET['message'])) : '';
1224
 
1225
- if (Ecwid_Message_Manager::disable_message($message)) {
1226
- wp_send_json(array('status' => 'success'));
1227
  }
1228
  }
1229
 
1230
- function ecwid_hide_vote_message()
1231
- {
1232
- update_option('ecwid_show_vote_message', false);
1233
  }
1234
 
1235
- function ecwid_get_title_separator()
1236
- {
1237
- $sep = apply_filters('document_title_separator', '|');
1238
 
1239
- if (!empty($sep)) {
1240
  return $sep;
1241
  }
1242
 
1243
- return apply_filters('ecwid_title_separator', '|');
1244
  }
1245
 
1246
  function ecwid_seo_title( $content, $sep = '', $seplocation = 'right' ) {
1247
 
1248
  $title = _ecwid_get_seo_title();
1249
-
1250
- if (!empty($title)) {
1251
-
1252
  if ( empty( $sep ) ) {
1253
  $sep = ecwid_get_title_separator();
1254
  }
1255
-
1256
- if ( $seplocation == 'right' )
1257
  return "$title $sep $content";
1258
- else
1259
  return "$content $sep $title";
 
1260
  }
1261
 
1262
  return $content;
1263
  }
1264
 
1265
 
1266
- function ecwid_seo_title_parts($parts)
1267
- {
1268
  $title = _ecwid_get_seo_title();
1269
- if ($title) {
1270
- array_unshift($parts, $title);
1271
  }
1272
 
1273
  return $parts;
1274
  }
1275
 
1276
- function _ecwid_get_seo_title()
1277
- {
1278
  $ecwid_seo_title = '';
1279
 
1280
  if ( ecwid_is_applicable_escaped_fragment() || Ecwid_Seo_Links::is_product_browser_url() ) {
1281
  $ecwid_seo_title = Ecwid_Static_Page::get_title();
1282
  }
1283
-
1284
  return $ecwid_seo_title;
1285
  }
1286
 
1287
- add_filter('oembed_endpoint_url', 'ecwid_oembed_url', 10, 3);
1288
 
1289
  function ecwid_oembed_url( $url, $permalink, $format ) {
1290
 
@@ -1329,18 +1305,17 @@ function ecwid_add_credits($powered_by)
1329
  return $powered_by;
1330
  }
1331
 
1332
- function ecwid_wrap_shortcode_content($content, $name, $attrs)
1333
- {
1334
- $version = get_option('ecwid_plugin_version');
1335
 
1336
- $lang = null;
1337
- if( isset( $attrs['lang'] ) ) {
1338
  $lang = $attrs['lang'];
1339
  }
1340
 
1341
  $shortcode_content = ecwid_get_scriptjs_code( $lang );
1342
 
1343
- if ($name == 'product2') {
1344
  $shortcode_content .= $content;
1345
  } else {
1346
  $shortcode_content .= "<div class=\"ecwid-shopping-cart-$name\">$content</div>";
@@ -1349,47 +1324,50 @@ function ecwid_wrap_shortcode_content($content, $name, $attrs)
1349
  $brand = Ecwid_Config::get_brand();
1350
 
1351
  $shortcode_content = "<!-- $brand shopping cart plugin v $version -->"
1352
- . $shortcode_content
1353
- . "<!-- END $brand Shopping Cart v $version -->";
1354
 
1355
- return apply_filters('ecwid_shortcode_content', $shortcode_content);
1356
  }
1357
 
1358
  function ecwid_get_scriptjs_code( $force_lang = null ) {
1359
  static $code = '';
1360
 
1361
- $store_id = get_ecwid_store_id();
1362
- $params = ecwid_get_scriptjs_params();
 
 
 
 
 
 
1363
 
1364
- $code = '<script data-cfasync="false" type="text/javascript" src="https://' . Ecwid_Config::get_scriptjs_domain() . '/script.js?' . $store_id . $params . '"></script>';
1365
  $code .= ecwid_sso();
1366
- $code .= '<script type="text/javascript">if (jQuery && jQuery.mobile) { jQuery.mobile.hashListeningEnabled = false; jQuery.mobile.pushStateEnabled=false; }</script>';
1367
 
1368
  return apply_filters( 'ecwid_scriptjs_code', $code );
1369
  }
1370
 
1371
-
1372
  add_filter( 'ecwid_lang', 'ecwid_get_default_language', 1, 1 );
1373
  function ecwid_get_default_language( $lang ) {
1374
  $locale = get_locale();
1375
 
1376
  if ( $locale ) {
1377
- $locales = explode( '_', $locale );
1378
- return $locales[0];
1379
- }
1380
 
1381
  return $lang;
1382
  }
1383
 
1384
-
1385
  function ecwid_get_scriptjs_params( $force_lang = null ) {
1386
 
1387
- if( is_null( $force_lang ) ) {
1388
  $force_lang = apply_filters( 'ecwid_lang', $force_lang );
1389
  }
1390
 
1391
  $store_id = get_ecwid_store_id();
1392
- $force_lang_str = !empty( $force_lang ) ? "&lang=$force_lang" : '';
1393
  $params = '&data_platform=wporg' . $force_lang_str;
1394
 
1395
  return $params;
@@ -1418,60 +1396,6 @@ function ecwid_minicart_shortcode($attributes) {
1418
  return $shortcode->render();
1419
  }
1420
 
1421
- function ecwid_get_search_js_code() {
1422
- return 'xSearch("style=");';
1423
- }
1424
-
1425
- function _ecwid_get_single_product_widget_parts_v1($attributes) {
1426
- return array(
1427
- 'display_items' => array(
1428
- 'picture' => '<div itemprop="picture"></div>',
1429
- 'title' => '<div class="ecwid-title" itemprop="title"></div>',
1430
- 'price' => '<div itemtype="http://schema.org/Offer" itemscope itemprop="offers">'
1431
- . '<div class="ecwid-productBrowser-price ecwid-price" itemprop="price"></div>'
1432
- . '</div>',
1433
- 'options' => '<div itemprop="options"></div>',
1434
- 'qty' => '<div itemprop="qty"></div>',
1435
- 'addtobag' => '<div itemprop="addtobag"></div>'
1436
- ),
1437
- 'opening_div' => sprintf('<div class="ecwid ecwid-SingleProduct ecwid-Product ecwid-Product-%d" '
1438
- . 'itemscope itemtype="http://schema.org/Product" '
1439
- . 'data-single-product-id="%d">', $attributes['id'], $attributes['id']),
1440
- 'widget_call' => '<script data-cfasync="false" type="text/javascript">xSingleProduct()</script>'
1441
- );
1442
- }
1443
-
1444
- function _ecwid_get_single_product_widget_parts_v2($attributes) {
1445
-
1446
- $price_location_attributes = ' data-spw-price-location="button"';
1447
- $bordered_class = ' ecwid-SingleProduct-v2-bordered';
1448
- if ($attributes['show_border'] == 0) {
1449
- $bordered_class = '';
1450
- }
1451
-
1452
- if ($attributes['show_price_on_button'] == 0) {
1453
- $price_location_attributes = '';
1454
- }
1455
-
1456
- return array(
1457
- 'display_items' => array(
1458
- 'picture' => '<div itemprop="picture"></div>',
1459
- 'title' => '<div class="ecwid-title" itemprop="title"></div>',
1460
- 'price' => '<div itemtype="http://schema.org/Offer" itemscope itemprop="offers">'
1461
- . '<div class="ecwid-productBrowser-price ecwid-price" itemprop="price"' . $price_location_attributes . '>'
1462
- . '<div itemprop="priceCurrency"></div>'
1463
- . '</div>'
1464
- . '</div>',
1465
- 'options' => '<div customprop="options"></div>',
1466
- 'qty' => '<div customprop="qty"></div>',
1467
- 'addtobag' => '<div customprop="addtobag"></div>'
1468
- ),
1469
- 'opening_div' => sprintf('<div class="ecwid ecwid-SingleProduct-v2' . $bordered_class . ' ecwid-Product ecwid-Product-%d"'
1470
- . 'itemscope itemtype="http://schema.org/Product" data-single-product-id="%d">', $attributes['id'], $attributes['id']),
1471
- 'widget_call' => '<script data-cfasync="false" type="text/javascript">xProduct()</script>'
1472
- );
1473
- }
1474
-
1475
  function ecwid_shortcode($attributes)
1476
  {
1477
  $custom_renderer = apply_filters( 'ecwid_shortcode_custom_renderer', null );
@@ -1641,7 +1565,7 @@ $content
1641
 
1642
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-nav-menus.php';
1643
 
1644
- $id = get_option("ecwid_store_page_id");
1645
  $_tmp_page = null;
1646
  if (!empty($id) and ($id > 0)) {
1647
  $_tmp_page = get_post($id);
@@ -1869,9 +1793,6 @@ function ecwid_get_update_params_options() {
1869
  Ecwid_Admin::OPTION_ENABLE_AUTO_MENUS_AUTO
1870
  )
1871
  ),
1872
- 'ecwid_print_html_catalog' => array(
1873
- 'type' => 'bool'
1874
- ),
1875
 
1876
  'ecwid_hide_prefetch' => array(
1877
  'values' => array(
@@ -1881,6 +1802,10 @@ function ecwid_get_update_params_options() {
1881
  )
1882
  ),
1883
 
 
 
 
 
1884
  Ecwid_Static_Page::OPTION_IS_ENABLED => array(
1885
  'values' => array(
1886
  Ecwid_Static_Page::OPTION_VALUE_AUTO,
@@ -1888,6 +1813,14 @@ function ecwid_get_update_params_options() {
1888
  Ecwid_Static_Page::OPTION_VALUE_DISABLED
1889
  )
1890
  ),
 
 
 
 
 
 
 
 
1891
 
1892
  'ecwid_api_status' => array(
1893
  'type' => 'string'
@@ -2840,11 +2773,13 @@ function ecwid_get_product_browser_url_script()
2840
  $url = esc_js( Ecwid_Store_Page::get_store_url() );
2841
  ob_start();
2842
  ?>
 
2843
  <script data-cfasync="false" type="text/javascript">
2844
  window.ec = window.ec || Object();
2845
  window.ec.config = window.ec.config || Object();
2846
  window.ec.config.store_main_page_url = '<?php echo esc_js( $url ); ?>';
2847
  </script>
 
2848
  <?php
2849
  $str = ob_get_clean();
2850
  }
@@ -2946,12 +2881,15 @@ function ecwid_sso() {
2946
  var ecwid_sso_profile = '<?php echo esc_js( $ecwid_sso_profile ); ?>';
2947
  window.EcwidSignInUrl = '<?php echo esc_js( $signin_url ); ?>';
2948
  window.EcwidSignOutUrl = '<?php echo esc_js( $signout_url ); ?>';
2949
- window.Ecwid.OnAPILoaded.add(function() {
2950
- window.Ecwid.setSignInUrls({
2951
- signInUrl: '<?php echo esc_js( $signin_url ); ?>',
2952
- signOutUrl: '<?php echo esc_js( $signout_url ); ?>'
 
 
 
2953
  });
2954
- });
2955
 
2956
  jQuery(document).ready(function() {
2957
  if (typeof Ecwid == 'undefined') return;
@@ -2971,7 +2909,6 @@ function ecwid_sso() {
2971
  }
2972
 
2973
  // from: http://www.php.net/manual/en/function.sha1.php#39492
2974
-
2975
  function ecwid_hmacsha1($data, $key) {
2976
  if (function_exists("hash_hmac")) {
2977
  return hash_hmac('sha1', $data, $key);
5
  Description: Ecwid is a free full-featured shopping cart. It can be easily integrated with any Wordpress blog and takes less than 5 minutes to set up.
6
  Text Domain: ecwid-shopping-cart
7
  Author: Ecwid Ecommerce
8
+ Version: 6.11
9
  Author URI: https://ecwid.to/ecwid-site
10
  License: GPLv2 or later
11
  */
46
 
47
  add_action( 'admin_init', 'ecwid_settings_api_init' );
48
  add_action( 'admin_init', 'ecwid_check_version' );
49
+ add_action( 'wp_ajax_ec_check_api_cache', 'ecwid_admin_check_api_cache' );
50
 
51
  add_action( 'admin_enqueue_scripts', 'ecwid_common_admin_scripts' );
52
  add_action( 'admin_enqueue_scripts', 'ecwid_register_admin_styles' );
76
  add_action( 'init', 'ecwid_check_api_cache' );
77
 
78
  add_action( 'template_redirect', 'ecwid_404_on_broken_escaped_fragment' );
79
+ // ecwid_apply_theme - why not init?
80
+ add_action( 'template_redirect', 'ecwid_apply_theme' );
81
 
82
  add_action( 'wp', 'ecwid_seo_ultimate_compatibility', 0 );
83
  add_action( 'wp', 'ecwid_remove_default_canonical' );
91
  add_action( 'wp_enqueue_scripts', 'ecwid_enqueue_frontend' );
92
  add_filter( 'wp_title', 'ecwid_seo_title', 10000, 3 );
93
  add_filter( 'document_title_parts', 'ecwid_seo_title_parts' );
 
94
  add_filter( 'widget_meta_poweredby', 'ecwid_add_credits' );
95
  add_filter( 'body_class', 'ecwid_body_class' );
96
  add_action( 'redirect_canonical', 'ecwid_redirect_canonical', 10, 2 );
134
 
135
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-nav-menus.php';
136
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-ajax-defer-renderer.php';
137
+ require_once ECWID_PLUGIN_DIR . 'includes/class-ec-store-defer-init.php';
138
 
139
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-store-page.php';
140
 
141
  require_once ECWID_PLUGIN_DIR . 'lib/ecwid_product.php';
142
  require_once ECWID_PLUGIN_DIR . 'lib/ecwid_category.php';
143
 
 
144
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-seo-links.php';
145
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-html-meta.php';
146
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-wp-dashboard-feed.php';
161
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-floating-minicart.php';
162
  }
163
 
164
+ if ( strpos( $version, '5.0' ) === 0 || version_compare( $version, '5.0' ) > 0 ) {
165
  require_once ECWID_PLUGIN_DIR . 'includes/gutenberg/class-ecwid-gutenberg.php';
166
  }
167
 
168
+ if ( strpos( $version, '5.5' ) === 0 || version_compare( $version, '5.5' ) >= 0 ) {
169
  require_once ECWID_PLUGIN_DIR . 'includes/class-ec-store-sitemap-provider.php';
170
  }
171
 
195
  'wordpress-seo-premium/wp-seo-premium.php' => 'wpseo',
196
  'divi-builder/divi-builder.php' => 'divibuilder',
197
  'autoptimize/autoptimize.php' => 'autoptimize',
 
198
  'js_composer/js_composer.php' => 'wpbakery-composer',
199
  'beaver-builder-lite-version/fl-builder.php' => 'beaver-builder',
200
  'bb-plugin/fl-builder.php' => 'beaver-builder',
250
  * http://core.trac.wordpress.org/browser/tags/3.6/wp-includes/shortcodes.php
251
  */
252
 
253
+ if ( ! function_exists( 'shortcode_exists' ) ) {
254
  function shortcode_exists( $tag ) {
255
  global $shortcode_tags;
256
  return array_key_exists( $tag, $shortcode_tags );
257
  }
258
  }
259
 
260
+ if ( ! function_exists( 'has_shortcode' ) ) {
261
  function has_shortcode( $content, $tag ) {
262
  if ( false === strpos( $content, '[' ) ) {
263
  return false;
282
  }
283
 
284
  if ( is_admin() ) {
285
+ $main_button_class = '';
286
+ if ( version_compare( $version, '3.8-beta' ) > 0 ) {
287
+ $main_button_class = 'button-primary';
288
  } else {
289
+ $main_button_class = 'pure-button pure-button-primary';
290
  }
291
 
292
+ define( 'ECWID_MAIN_BUTTON_CLASS', $main_button_class );
293
  }
294
 
295
+ function ecwid_body_class( $classes ) {
 
296
  if ( Ecwid_Store_Page::is_store_page() ) {
297
  $classes[] = 'ecwid-shopping-cart';
298
  }
300
  return $classes;
301
  }
302
 
303
+ function ecwid_redirect_canonical( $redirect_url, $requested_url ) {
304
+ if ( ! is_front_page() ) {
305
  return $redirect_url;
306
  }
307
 
308
+ if ( strpos( $requested_url, '_escaped_fragment_' ) === false ) {
309
  return $redirect_url;
310
  }
311
 
312
+ $parsed = parse_url( $requested_url );
313
  $query = array();
314
+ parse_str( $parsed['query'], $query );
315
 
316
+ if ( ! array_key_exists( '_escaped_fragment_', $query) ) {
317
  return $redirect_url;
318
  }
319
 
320
+ if ( ! Ecwid_Store_Page::is_store_page() ) {
321
  return $redirect_url;
322
  }
323
 
354
  }
355
  }
356
 
357
+ add_action( 'wp_ajax_ecwid_get_product_info', 'ecwid_ajax_get_product_info' );
358
+ add_action( 'wp_ajax_nopriv_ecwid_get_product_info', 'ecwid_ajax_get_product_info' );
359
 
360
+ add_filter( 'redirect_canonical', 'ecwid_redirect_canonical2', 10, 3 );
361
 
362
+ function ecwid_redirect_canonical2( $redir, $req ) {
363
  global $wp_query;
364
 
365
  $adds_slash = $req . '/' == $redir;
366
+ $adds_slash |= urldecode( $req . '/' ) == urldecode( $redir );
367
+
368
+ if ( Ecwid_Store_Page::is_store_page() && $adds_slash ) {
369
  return $req;
370
  }
371
 
374
 
375
  add_action( 'current_screen', 'ecwid_add_deactivation_popup' );
376
 
377
+ function ecwid_add_deactivation_popup() {
 
378
  if ( get_current_screen()->id == 'plugins' ) {
379
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-popup-deactivate.php';
380
+
381
  $popup = new Ecwid_Popup_Deactivate();
382
+
383
+ if ( ! $popup->is_disabled() ) {
384
  Ecwid_Popup::add_popup( $popup );
385
  }
386
  }
388
 
389
  function ecwid_enqueue_frontend() {
390
  global $ecwid_current_theme;
391
+
392
+ if ( $ecwid_current_theme && $ecwid_current_theme->historyjs_html4mode || get_option( 'ecwid_historyjs_html4mode' ) ) {
393
  wp_enqueue_script('ecwid-historyjs-wa', ECWID_PLUGIN_URL . 'js/historywa.js');
394
  }
395
 
396
+ $version = get_bloginfo( 'version' );
397
+ if ( ! wp_script_is( 'jquery-ui-widget' ) && version_compare( $version, '5.6' ) < 0 ) {
398
+ wp_enqueue_script( 'jquery-ui-widget', includes_url() . 'js/jquery/ui/widget.min.js', array( 'jquery' ) );
399
  }
400
 
401
+ wp_enqueue_style( 'ecwid-css', ECWID_PLUGIN_URL . 'css/frontend.css', array(), get_option( 'ecwid_plugin_version' ) );
402
+
403
+ wp_enqueue_script( 'ecwid-frontend-js', ECWID_PLUGIN_URL . 'js/frontend.js', array( 'jquery' ), get_option( 'ecwid_plugin_version' ), true );
404
  wp_localize_script( 'ecwid-frontend-js', 'ecwidParams', array(
405
  'useJsApiToOpenStoreCategoriesPages' => Ecwid_Nav_Menus::should_use_js_api_for_categories_menu(),
406
  'storeId' => get_ecwid_store_id()
407
  ));
408
+
409
  if ( get_post() && get_post()->post_type == Ecwid_Products::POST_TYPE_PRODUCT ) {
410
  wp_enqueue_script( 'ecwid-post-product', ECWID_PLUGIN_URL . 'js/post-product.js', array(), get_option( 'ecwid_plugin_version' ), TRUE );
411
 
412
+ $meta = get_post_meta( get_the_ID(), 'ecwid_id' );
413
 
414
  wp_localize_script( 'ecwid-post-product', 'ecwidPost', array(
415
  'productId' => $meta[0],
417
  ) );
418
  }
419
 
420
+ if ( is_active_widget( false, false, 'ecwidrecentlyviewed' ) ) {
421
+ wp_enqueue_script( 'ecwid-recently-viewed', ECWID_PLUGIN_URL . 'js/recently-viewed-common.js', array( 'jquery', 'utils' ), get_option( 'ecwid_plugin_version' ), true );
422
 
423
  wp_localize_script(
424
  'ecwid-products-list-js',
430
  );
431
  }
432
 
433
+ if ( is_plugin_active( 'contact-form-7-designer/cf7-styles.php' ) ) {
434
+ wp_enqueue_script( 'ecwid-cf7designer', ECWID_PLUGIN_URL . 'js/cf7designer.js', array(), get_option( 'ecwid-plugin-version' ), true );
435
  }
436
 
437
+ if ( current_user_can( 'manage_options' ) ) {
438
+ wp_enqueue_style( 'ecwid-fonts-css', ECWID_PLUGIN_URL . 'css/fonts.css', array(), get_option( 'ecwid_plugin_version' ) );
439
  }
440
 
441
  if ( Ecwid_Store_Page::is_store_page() && ( current_user_can( Ecwid_Admin::get_capability() ) || is_admin_bar_showing() ) ) {
442
  $is_post_edit_replace = true;
443
 
444
+ if ( Ecwid_Config::is_wl() && ! Ecwid_Api_V3::is_available() ) {
445
  $is_post_edit_replace = false;
446
  }
447
+
448
+ if ( $is_post_edit_replace ) {
449
 
450
  $post_edit_url = 'https://my.ecwid.com/#';
451
  $is_api_available = false;
452
 
453
+ if ( Ecwid_Config::is_wl() || Ecwid_Api_V3::is_available() ) {
454
  $post_edit_url = get_admin_url() . 'admin.php?page=ec-store&ec-store-page=';
455
  $is_api_available = true;
456
  }
457
 
458
+ if ( ! ecwid_is_demo_store() ) {
459
  wp_enqueue_script( 'ecwid-admin-bar-js', ECWID_PLUGIN_URL . 'js/admin-bar.js', array( 'jquery' ), get_option( 'ecwid_plugin_version' ) );
460
  wp_localize_script( 'ecwid-admin-bar-js', 'ecwidEditPostLinkParams', array(
461
  'languages' => array(
499
  function ecwid_add_chameleon( $js ) {
500
 
501
  $colors = array();
502
+ foreach ( array( 'foreground', 'background', 'link', 'price', 'button' ) as $kind ) {
503
  $color = get_option( 'ecwid_chameleon_colors_' . $kind );
504
  if ( $color ) {
505
+ $colors[ 'color-' . $kind ] = $color;
506
  }
507
  }
508
 
509
+ if ( ! get_option( 'ecwid_use_chameleon' ) && empty( $colors ) ) {
510
  return $js;
511
  }
512
 
514
  $colors = 'auto';
515
  }
516
 
517
+ $colors = json_encode( $colors );
518
  $font = '"auto"';
519
 
520
  $chameleon = apply_filters( 'ecwid_chameleon_settings', array( 'colors' => $colors, 'font' => $font ) );
521
 
522
+ if ( ! is_array( $chameleon ) ) {
523
  $chameleon = array(
524
  'colors' => $colors,
525
+ 'font' => $font,
526
  );
527
  }
528
 
529
+ if ( ! isset( $chameleon['colors'] ) ) {
530
+ $chameleon['colors'] = json_encode( $colors );
531
  }
532
 
533
+ if ( ! isset( $chameleon['font'] ) ) {
534
  $chameleon['font'] = $font;
535
  }
536
 
653
  }
654
  }
655
 
656
+ function ecwid_check_version() {
657
+ $plugin_data = get_plugin_data( __FILE__ );
 
658
  $current_version = $plugin_data['Version'];
659
+ $stored_version = get_option( 'ecwid_plugin_version', null );
660
 
661
+ $migration_since_version = get_option( 'ecwid_plugin_migration_since_version', null );
662
+ if ( is_null( $migration_since_version ) ) {
663
+ update_option( 'ecwid_plugin_migration_since_version', $current_version );
664
  }
665
 
666
+ $fresh_install = ! $stored_version;
667
+ $upgrade = $stored_version && version_compare( $current_version, $stored_version ) > 0;
668
 
669
+ if ( $fresh_install ) {
670
+
671
+ do_action( 'ecwid_plugin_installed', $current_version );
672
+ add_option( 'ecwid_plugin_version', $current_version );
673
 
 
 
 
674
  // Called in Ecwid_Seo_Links->on_fresh_install
675
  do_action( 'ecwid_on_fresh_install' );
676
 
677
+ } elseif ( $upgrade ) {
678
+
679
+ do_action( 'ecwid_plugin_upgraded', array( 'old' => $stored_version, 'new' => $current_version ) );
680
+ update_option( 'ecwid_plugin_version', $current_version );
681
 
 
 
 
682
  do_action( 'ecwid_on_plugin_upgrade' );
683
+ }//end if
684
 
685
+ if ( $fresh_install || $upgrade || isset( $_GET['ecwid_reinit'] ) ) {
686
 
687
  add_option( Ecwid_Seo_Links::OPTION_ENABLED, false );
688
 
689
+ if ( ecwid_migrations_is_original_plugin_version_older_than( '4.3' ) ) {
690
+ add_option( 'ecwid_fetch_url_use_file_get_contents', '' );
691
+ add_option( 'ecwid_remote_get_timeout', '5' );
692
  }
693
 
694
  add_option( 'ecwid_support_email', 'wordpress@ecwid.com' );
695
 
696
+ add_option( 'ecwid_enable_sso' );
697
 
698
  add_option( Ecwid_Products::OPTION_ENABLED, Ecwid_Products::is_enabled() );
699
 
700
+ add_option( 'ecwid_disable_pb_url', false );
701
+ add_option( 'ecwid_historyjs_html4mode', false );
702
 
703
+ add_option( Ecwid_Widget_Floating_Shopping_Cart::OPTION_DISPLAY_POSITION, '' );
704
 
705
  // Since 5.4
706
+ delete_option( 'ecwid_use_new_search' );
707
+ delete_option( 'ecwid_use_new_categories' );
708
  // /Since 5.4
709
 
710
  // Since 5.4.2
711
+ delete_option( 'ecwid_hide_appearance_menu' );
712
+
713
+ // Since 5.4.3
714
  add_option( Ecwid_Widget_Floating_Shopping_Cart::OPTION_MOVE_INTO_BODY, '' );
715
+
716
  // Since 5.7.3
717
  delete_option( 'ecwid_use_js_api_to_open_store_pages' );
718
 
719
+ // Since 5.7.4
720
  update_option( 'ecwid_use_js_api_to_open_store_categories_pages', Ecwid_Nav_Menus::OPTVAL_USE_JS_API_FOR_CATS_MENU_AUTO );
721
+
722
  // Since 5.8
723
  add_option( Ecwid_Admin::OPTION_ENABLE_AUTO_MENUS, 'auto' );
724
 
727
 
728
  // Since 5.8.1+
729
  add_option( Ecwid_Products::OPTION_SYNC_LIMIT, 20 );
730
+
731
  // Since 6.0.x
732
  add_option( 'ecwid_hide_prefetch', 'off' );
733
 
734
+ // Since 6.1.x
735
  if ( class_exists( 'Ecwid_Floating_Minicart' ) ) {
736
  Ecwid_Floating_Minicart::create_default_options();
737
  }
738
  add_option( 'ecwid_hide_old_minicart', ecwid_is_recent_installation() );
739
+
740
  Ecwid_Config::load_from_ini();
741
 
742
  // Since 6.2.x
743
  delete_option( 'force_scriptjs_render' );
744
+
745
  // Since 6.4.x
746
  add_option( EcwidPlatform::OPTION_LOG_CACHE );
747
+
748
  // Since 6.4.8
749
  add_option( 'ecwid_hide_canonical', false );
750
 
751
  // Since 6.4.9
752
  add_option( Ecwid_Theme_Base::OPTION_LEGACY_CUSTOM_SCROLLER, false );
753
+
754
  // Since 6.4.9+
755
  add_option( 'ecwid_remove_emoji', 'Y' );
756
 
757
  // Since 6.4.14+
758
  add_option( Ecwid_Store_Page::OPTION_REPLACE_TITLE, $fresh_install ? 'Y' : '' );
759
+
760
  do_action( 'ecwid_on_plugin_update' );
761
 
762
+ Ecwid_Store_Page::add_store_page( get_option( 'ecwid_store_page_id' ) );
763
+ Ecwid_Store_Page::add_store_page( get_option( 'ecwid_store_page_id_auto' ) );
764
 
765
+ if ( Ecwid_Store_Page::get_current_store_page_id() ) {
766
+ delete_option( 'ecwid_store_page_id_auto' );
767
  }
768
 
769
  Ecwid_Api_V3::reset_api_status();
770
  flush_rewrite_rules();
771
+ }//end if
772
+
773
+ add_option( 'ecwid_disable_dashboard', '' );
774
  }
775
 
776
  function ecwid_get_woocommerce_status() {
794
  return $woo;
795
  }
796
 
797
+ function ecwid_is_recent_installation() {
798
+ return get_option( 'ecwid_plugin_migration_since_version' ) == get_option('ecwid_plugin_version' );
 
799
  }
800
 
801
+ function ecwid_migrations_is_original_plugin_version_older_than( $version ) {
802
+ $migration_since_version = get_option( 'ecwid_plugin_migration_since_version', null );
803
+ return version_compare( $migration_since_version, $version ) < 0;
 
804
  }
805
 
806
  function ecwid_log_error($message)
827
  update_option('ecwid_error_log', json_encode($errors));
828
  }
829
 
 
 
 
 
 
 
830
  function ecwid_override_option($name, $new_value = null)
831
  {
832
  static $overridden = array();
841
  update_option($name, $overridden[$name]);
842
  }
843
  }
844
+
845
+ function ecwid_tinymce_init( $in ) {
846
+ if ( ! empty( $in['extended_valid_elements'] ) ) {
847
  $in['extended_valid_elements'] .= ',';
848
  } else {
849
  $in['extended_valid_elements'] = '';
854
  return $in;
855
  }
856
 
857
+ function ecwid_seo_ultimate_compatibility() {
 
858
  global $seo_ultimate;
859
 
860
+ if ( ! $seo_ultimate ) {
861
+ return;
862
+ }
863
+ if ( ! Ecwid_Store_Page::is_store_page() ) {
864
+ return;
865
+ }
866
+
867
  if ( isset( $_GET['_escaped_fragment_'] ) || ( Ecwid_Seo_Links::is_enabled() && Ecwid_Seo_Links::is_product_browser_url() ) ) {
868
+ remove_action( 'template_redirect', array( $seo_ultimate->modules['titles'], 'before_header' ), 0 );
869
+ remove_action( 'wp_head', array( $seo_ultimate->modules['titles'], 'after_header' ), 1000 );
870
+ remove_action( 'su_head', array( $seo_ultimate->modules['meta-descriptions'], 'head_tag_output' ) );
871
+ remove_action( 'su_head', array( $seo_ultimate->modules['canonical'], 'link_rel_canonical_tag' ) );
872
+ remove_action( 'su_head', array( $seo_ultimate->modules['canonical'], 'http_link_rel_canonical' ) );
873
  }
874
  }
875
 
876
+ function ecwid_remove_default_canonical() {
 
877
  if ( Ecwid_Store_Page::is_store_page() ) {
878
+ remove_action( 'wp_head', 'rel_canonical' );
879
  }
880
  }
881
 
882
+ function ecwid_seo_compatibility_init( $title ) {
883
+ if ( ! array_key_exists( '_escaped_fragment_', $_GET ) || ! Ecwid_Store_Page::is_store_page() ) {
884
+ return $title;
885
+ }
 
886
 
887
  // Platinum SEO Pack
888
+ // Canonical
889
+ ecwid_override_option( 'psp_canonical', false );
890
+ // Title
891
+ ecwid_override_option( 'aiosp_rewrite_titles', false );
892
 
893
+ add_action( 'amt_basic_metadata_head', 'ecwid_amt_remove_description' );
894
  return $title;
 
895
  }
896
 
897
+ function ecwid_amt_remove_description( $params ) {
898
+ foreach ( $params as $key => $value ) {
899
+ if ( preg_match( '/meta name="description"/', $value ) ) {
900
+ unset( $params[ $key ] );
 
901
  }
902
  }
903
 
904
  return $params;
905
  }
906
 
907
+ function ecwid_seo_compatibility_restore() {
908
+ if ( ! array_key_exists( '_escaped_fragment_', $_GET ) || ! Ecwid_Store_Page::is_store_page() ) {
909
+ return;
910
+ }
 
911
 
912
+ ecwid_override_option( 'psp_canonical' );
913
+ ecwid_override_option( 'aiosp_rewrite_titles' );
914
  }
915
 
916
  function ecwid_check_api_cache() {
917
  EcwidPlatform::cache_log_record( 'init', array() );
 
 
918
 
919
+ $last_cache = get_option( 'ecwid_last_api_cache_check' );
920
+
921
+ if ( time() - $last_cache > HOUR_IN_SECONDS ) {
922
  ecwid_invalidate_cache();
923
  }
924
  }
925
 
 
926
  function ecwid_enqueue_cache_control() {
927
+ wp_enqueue_script( 'ecwid-defer-actions', ECWID_PLUGIN_URL . 'js/defer-actions.js', array(), get_option( 'ecwid_plugin_version' ), true );
928
 
929
+ wp_localize_script(
930
+ 'ecwid-defer-actions',
931
+ 'ecwidCacheControlParams',
932
+ array( 'ajax_url' => admin_url( 'admin-ajax.php' ) )
933
+ );
934
  }
935
 
936
+ function ecwid_admin_check_api_cache() {
937
+ $is_ajax_check_api_cache = isset( $_GET['action'] ) && $_GET['action'] == 'ec_check_api_cache';
 
938
  $is_doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX;
939
+ $is_get_request = isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] != 'GET';
940
 
941
+ if ( ! $is_ajax_check_api_cache && ( $is_doing_ajax || $is_get_request ) ) return; //phpcs:ignore Generic.ControlStructures.InlineControlStructure.NotAllowed
942
 
943
  EcwidPlatform::cache_log_record( 'admin_init', array() );
944
 
945
  $last_cache = get_option( 'ecwid_last_api_cache_check' );
946
 
947
+ if ( Ecwid_Api_V3::get_api_status() == Ecwid_Api_V3::API_STATUS_OK ) {
948
  $check_time_period = 5 * MINUTE_IN_SECONDS;
949
+ } else {
950
  $check_time_period = MINUTE_IN_SECONDS;
951
+ }
952
 
953
  if ( time() - $last_cache > $check_time_period ) {
954
  Ecwid_Api_V3::reset_api_status();
957
  ecwid_regular_cache_check();
958
  }
959
 
960
+ function ecwid_invalidate_cache( $full_reset = false ) {
 
961
  if ( $full_reset ) {
962
  ecwid_full_cache_reset();
963
  return;
964
  }
965
+
966
  ecwid_regular_cache_check();
967
  }
968
 
969
+ function ecwid_regular_cache_check() {
 
970
  static $already_checked = false;
971
+
972
+ if ( Ecwid_Api_V3::is_available() && ! $already_checked ) {
973
+
974
  $already_checked = true;
975
  $api = new Ecwid_Api_V3();
976
 
977
  $stats = $api->get_store_update_stats();
978
 
979
+ EcwidPlatform::cache_log_record( 'reg cache check', array( 'stats' => $stats ) );
980
 
981
  if ( $stats ) {
982
+ //phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
983
  EcwidPlatform::invalidate_products_cache_from( strtotime( $stats->productsUpdated ) );
984
  EcwidPlatform::invalidate_categories_cache_from( strtotime( $stats->categoriesUpdated ) );
985
  EcwidPlatform::invalidate_profile_cache_from( strtotime( $stats->profileUpdated ) );
986
  update_option( 'ecwid_last_api_cache_check', time() );
987
+ //phpcs:enable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
988
  }
989
 
990
+ $last_transients = get_option( 'ecwid_last_transients_check' );
991
 
992
+ if ( time() - $last_transients > MONTH_IN_SECONDS ) {
993
  EcwidPlatform::clear_all_transients();
994
  update_option( 'ecwid_last_transients_check', time() );
995
  }
997
  if ( EcwidPlatform::is_need_clear_transients() ) {
998
  EcwidPlatform::clear_all_transients();
999
  }
1000
+ }//end if
1001
  }
1002
 
1003
+ function ecwid_full_cache_reset() {
 
1004
  Ecwid_Api_V3::reset_api_status();
1005
 
1006
  EcwidPlatform::invalidate_categories_cache_from( time() );
1014
 
1015
  $p = new Ecwid_Products();
1016
  $p->reset_dates();
1017
+
1018
  update_option( Ecwid_Api_V3::OPTION_API_STATUS, Ecwid_Api_V3::API_STATUS_OK );
1019
  update_option( 'ecwid_last_api_cache_check', time() );
1020
  }
1028
  $theme = ecwid_get_theme_name();
1029
  $store_url = Ecwid_Store_Page::get_store_url();
1030
 
 
 
1031
  if (!is_admin()) {
1032
  $subject = sprintf( __('%s plugin doesn\'t work well with my "%s" theme', 'ecwid-shopping-cart'), Ecwid_Config::get_brand(), $theme );
1033
 
1122
 
1123
  if ( class_exists( 'Ecwid_Gutenberg' ) && Ecwid_Gutenberg::content_has_productbrowser( $content ) !== false ) {
1124
  return true;
1125
+ }
1126
 
1127
+ $result = has_shortcode( $content, 'ecwid_productbrowser' );
1128
+ if ( $result ) {
1129
  return $result;
1130
  }
1131
+
1132
  foreach ( Ecwid_Shortcode_Base::get_store_shortcode_names() as $shortcode_name ) {
1133
+ if ( has_shortcode( $content, $shortcode_name ) ) {
1134
  $shortcodes = ecwid_find_shortcodes( $content, $shortcode_name );
1135
  if ( $shortcodes ) foreach ( $shortcodes as $shortcode ) {
1136
 
1144
  }
1145
  }
1146
  }
 
1147
  }
1148
 
1149
  return $result;
1150
  }
1151
 
1152
+ function ecwid_get_current_user_locale() {
1153
+ if ( function_exists( 'get_user_locale' ) ) {
 
1154
  $lang = get_user_locale();
1155
  } else {
1156
  $lang = get_locale();
1157
  }
1158
+
1159
  return $lang;
1160
  }
1161
 
1179
  return true;
1180
  }
1181
 
1182
+ function ecwid_trim_description( $description ) {
 
1183
  return Ecwid_HTML_Meta::process_raw_description( $description, ECWID_TRIMMED_DESCRIPTION_LENGTH );
1184
  }
1185
 
1186
  add_action( 'wp_ajax_ecwid_deactivate_feedback', 'ecwid_ajax_deactivate_feedback' );
1187
+ function ecwid_ajax_deactivate_feedback() {
1188
+ if ( ! current_user_can( Ecwid_Admin::get_capability() ) ) {
1189
+ die();
1190
+ }
1191
+
 
1192
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-popup-deactivate.php';
1193
  $popup = new Ecwid_Popup_Deactivate();
1194
  $popup->ajax_deactivate_feedback();
1195
  }
1196
 
1197
+ function ecwid_ajax_hide_message( $params ) {
1198
+ if ( ! current_user_can( 'manage_options' ) ) {
 
1199
  return;
1200
  }
1201
 
1202
+ $message = isset( $_GET['message'] ) ? sanitize_text_field( wp_unslash( $_GET['message'] ) ) : '';
1203
 
1204
+ if ( Ecwid_Message_Manager::disable_message( $message ) ) {
1205
+ wp_send_json( array( 'status' => 'success' ) );
1206
  }
1207
  }
1208
 
1209
+ function ecwid_hide_vote_message() {
1210
+ update_option( 'ecwid_show_vote_message', false );
 
1211
  }
1212
 
1213
+ function ecwid_get_title_separator() {
1214
+ $sep = apply_filters( 'document_title_separator', '|' );
 
1215
 
1216
+ if ( ! empty( $sep ) ) {
1217
  return $sep;
1218
  }
1219
 
1220
+ return apply_filters( 'ecwid_title_separator', '|' );
1221
  }
1222
 
1223
  function ecwid_seo_title( $content, $sep = '', $seplocation = 'right' ) {
1224
 
1225
  $title = _ecwid_get_seo_title();
1226
+
1227
+ if ( ! empty( $title ) ) {
1228
+
1229
  if ( empty( $sep ) ) {
1230
  $sep = ecwid_get_title_separator();
1231
  }
1232
+
1233
+ if ( $seplocation == 'right' ) {
1234
  return "$title $sep $content";
1235
+ } else {
1236
  return "$content $sep $title";
1237
+ }
1238
  }
1239
 
1240
  return $content;
1241
  }
1242
 
1243
 
1244
+ function ecwid_seo_title_parts( $parts ) {
 
1245
  $title = _ecwid_get_seo_title();
1246
+ if ( $title ) {
1247
+ array_unshift( $parts, $title );
1248
  }
1249
 
1250
  return $parts;
1251
  }
1252
 
1253
+ function _ecwid_get_seo_title() {
 
1254
  $ecwid_seo_title = '';
1255
 
1256
  if ( ecwid_is_applicable_escaped_fragment() || Ecwid_Seo_Links::is_product_browser_url() ) {
1257
  $ecwid_seo_title = Ecwid_Static_Page::get_title();
1258
  }
1259
+
1260
  return $ecwid_seo_title;
1261
  }
1262
 
1263
+ add_filter( 'oembed_endpoint_url', 'ecwid_oembed_url', 10, 3 );
1264
 
1265
  function ecwid_oembed_url( $url, $permalink, $format ) {
1266
 
1305
  return $powered_by;
1306
  }
1307
 
1308
+ function ecwid_wrap_shortcode_content( $content, $name, $attrs ) {
1309
+ $version = get_option( 'ecwid_plugin_version' );
 
1310
 
1311
+ $lang = null;
1312
+ if ( isset( $attrs['lang'] ) ) {
1313
  $lang = $attrs['lang'];
1314
  }
1315
 
1316
  $shortcode_content = ecwid_get_scriptjs_code( $lang );
1317
 
1318
+ if ( $name == 'product2' ) {
1319
  $shortcode_content .= $content;
1320
  } else {
1321
  $shortcode_content .= "<div class=\"ecwid-shopping-cart-$name\">$content</div>";
1324
  $brand = Ecwid_Config::get_brand();
1325
 
1326
  $shortcode_content = "<!-- $brand shopping cart plugin v $version -->"
1327
+ . $shortcode_content
1328
+ . "<!-- END $brand Shopping Cart v $version -->";
1329
 
1330
+ return apply_filters( 'ecwid_shortcode_content', $shortcode_content );
1331
  }
1332
 
1333
  function ecwid_get_scriptjs_code( $force_lang = null ) {
1334
  static $code = '';
1335
 
1336
+ $code = '<!--noptimize-->';
1337
+
1338
+ if ( ! Ec_Store_Defer_Init::is_enabled() ) {
1339
+ $store_id = get_ecwid_store_id();
1340
+ $params = ecwid_get_scriptjs_params();
1341
+
1342
+ $code .= '<script data-cfasync="false" type="text/javascript" src="https://' . Ecwid_Config::get_scriptjs_domain() . '/script.js?' . $store_id . $params . '"></script>'; //phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
1343
+ }
1344
 
 
1345
  $code .= ecwid_sso();
1346
+ $code .= '<script type="text/javascript">if (typeof jQuery !== undefined && jQuery.mobile) { jQuery.mobile.hashListeningEnabled = false; jQuery.mobile.pushStateEnabled=false; }</script><!--/noptimize-->';
1347
 
1348
  return apply_filters( 'ecwid_scriptjs_code', $code );
1349
  }
1350
 
 
1351
  add_filter( 'ecwid_lang', 'ecwid_get_default_language', 1, 1 );
1352
  function ecwid_get_default_language( $lang ) {
1353
  $locale = get_locale();
1354
 
1355
  if ( $locale ) {
1356
+ $locales = explode( '_', $locale );
1357
+ return $locales[0];
1358
+ }
1359
 
1360
  return $lang;
1361
  }
1362
 
 
1363
  function ecwid_get_scriptjs_params( $force_lang = null ) {
1364
 
1365
+ if ( is_null( $force_lang ) ) {
1366
  $force_lang = apply_filters( 'ecwid_lang', $force_lang );
1367
  }
1368
 
1369
  $store_id = get_ecwid_store_id();
1370
+ $force_lang_str = ! empty( $force_lang ) ? "&lang=$force_lang" : '';
1371
  $params = '&data_platform=wporg' . $force_lang_str;
1372
 
1373
  return $params;
1396
  return $shortcode->render();
1397
  }
1398
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1399
  function ecwid_shortcode($attributes)
1400
  {
1401
  $custom_renderer = apply_filters( 'ecwid_shortcode_custom_renderer', null );
1565
 
1566
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-nav-menus.php';
1567
 
1568
+ $id = get_option( "ecwid_store_page_id" );
1569
  $_tmp_page = null;
1570
  if (!empty($id) and ($id > 0)) {
1571
  $_tmp_page = get_post($id);
1793
  Ecwid_Admin::OPTION_ENABLE_AUTO_MENUS_AUTO
1794
  )
1795
  ),
 
 
 
1796
 
1797
  'ecwid_hide_prefetch' => array(
1798
  'values' => array(
1802
  )
1803
  ),
1804
 
1805
+ 'ecwid_print_html_catalog' => array(
1806
+ 'type' => 'bool'
1807
+ ),
1808
+
1809
  Ecwid_Static_Page::OPTION_IS_ENABLED => array(
1810
  'values' => array(
1811
  Ecwid_Static_Page::OPTION_VALUE_AUTO,
1813
  Ecwid_Static_Page::OPTION_VALUE_DISABLED
1814
  )
1815
  ),
1816
+
1817
+ Ec_Store_Defer_Init::OPTION_ENABLED => array(
1818
+ 'values' => array(
1819
+ Ec_Store_Defer_Init::OPTION_VALUE_AUTO,
1820
+ Ec_Store_Defer_Init::OPTION_VALUE_ENABLED,
1821
+ Ec_Store_Defer_Init::OPTION_VALUE_DISABLED
1822
+ )
1823
+ ),
1824
 
1825
  'ecwid_api_status' => array(
1826
  'type' => 'string'
2773
  $url = esc_js( Ecwid_Store_Page::get_store_url() );
2774
  ob_start();
2775
  ?>
2776
+ <!--noptimize-->
2777
  <script data-cfasync="false" type="text/javascript">
2778
  window.ec = window.ec || Object();
2779
  window.ec.config = window.ec.config || Object();
2780
  window.ec.config.store_main_page_url = '<?php echo esc_js( $url ); ?>';
2781
  </script>
2782
+ <!--/noptimize-->
2783
  <?php
2784
  $str = ob_get_clean();
2785
  }
2881
  var ecwid_sso_profile = '<?php echo esc_js( $ecwid_sso_profile ); ?>';
2882
  window.EcwidSignInUrl = '<?php echo esc_js( $signin_url ); ?>';
2883
  window.EcwidSignOutUrl = '<?php echo esc_js( $signout_url ); ?>';
2884
+
2885
+ if( typeof Ecwid != 'undefined' ) {
2886
+ window.Ecwid.OnAPILoaded.add(function() {
2887
+ window.Ecwid.setSignInUrls({
2888
+ signInUrl: '<?php echo esc_js( $signin_url ); ?>',
2889
+ signOutUrl: '<?php echo esc_js( $signout_url ); ?>'
2890
+ });
2891
  });
2892
+ }
2893
 
2894
  jQuery(document).ready(function() {
2895
  if (typeof Ecwid == 'undefined') return;
2909
  }
2910
 
2911
  // from: http://www.php.net/manual/en/function.sha1.php#39492
 
2912
  function ecwid_hmacsha1($data, $key) {
2913
  if (function_exists("hash_hmac")) {
2914
  return hash_hmac('sha1', $data, $key);
includes/class-ec-store-defer-init.php ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Ec_Store_Defer_Init {
3
+
4
+ const OPTION_ENABLED = 'ecwid_defer_store_init_enabled';
5
+
6
+ const OPTION_VALUE_ENABLED = 'Y';
7
+ const OPTION_VALUE_DISABLED = 'N';
8
+ const OPTION_VALUE_AUTO = '';
9
+
10
+ public function __construct() {
11
+ if ( ! is_admin() ) {
12
+ add_action( 'wp_footer', 'Ec_Store_Defer_Init::defer_script_js_load' );
13
+ }
14
+ }
15
+
16
+ public static function is_enabled() {
17
+ if ( array_key_exists( 'ec-enable-defer-store-init', $_GET ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
18
+ return true;
19
+ }
20
+
21
+ $default_value = self::OPTION_VALUE_DISABLED;
22
+
23
+ $is_needed_store_id = ! ecwid_is_demo_store() && get_ecwid_store_id() % 4 === 0;
24
+ $is_auto = empty( get_option( self::OPTION_ENABLED ) );
25
+
26
+ if ( $is_needed_store_id && $is_auto ) {
27
+ $default_value = self::OPTION_VALUE_ENABLED;
28
+ }
29
+
30
+ if ( get_option( self::OPTION_ENABLED, $default_value ) !== self::OPTION_VALUE_ENABLED ) {
31
+ return false;
32
+ }
33
+
34
+ return apply_filters( 'ecwid_is_defer_store_init_enabled', true );
35
+ }
36
+
37
+ public static function defer_script_js_load() {
38
+ if ( ! self::is_enabled() ) {
39
+ return false;
40
+ }
41
+
42
+ $hide_defer_load_script = apply_filters( 'ecwid_hide_defer_load_script', false );
43
+ if ( $hide_defer_load_script ) {
44
+ return false;
45
+ }
46
+
47
+ $widgets = apply_filters( 'ecwid_defer_widgets', array() );
48
+
49
+ $ecwid_store_id = get_ecwid_store_id();
50
+ $app_ecwid_com = Ecwid_Config::get_scriptjs_domain();
51
+
52
+ $lang = ecwid_get_current_user_locale();
53
+ $lang = apply_filters( 'ecwid_lang', $lang );
54
+
55
+ $script_src = "https://$app_ecwid_com/script.js?$ecwid_store_id&lang=$lang";
56
+ ?>
57
+ <script data-cfasync="false" type="text/javascript">
58
+ (function () {
59
+ var ec_widgets = <?php echo wp_json_encode( $widgets ); ?>
60
+
61
+ window.ecwid_script_defer = true;
62
+ window._xnext_initialization_scripts = window._xnext_initialization_scripts || [];
63
+ window._xnext_initialization_scripts.push(...ec_widgets);
64
+
65
+ var ecwidLazyScriptjsLoad = function() {
66
+ if ( ! document.getElementById( 'ecwid-script' ) ) {
67
+ var script = document.createElement('script');
68
+ script.charset = 'utf-8';
69
+ script.type = 'text/javascript';
70
+ script.src = '<?php echo esc_attr( $script_src ); ?>';
71
+ script.id = 'ecwid-script';
72
+ script.setAttribute('data-cfasync', 'false');
73
+
74
+ document.body.appendChild(script);
75
+
76
+ script.addEventListener('load', function() {
77
+ var nodes = document.getElementsByClassName('ec-cart-widget')
78
+ if (nodes.length > 0) {
79
+ Ecwid.init();
80
+ }
81
+
82
+ if( typeof ecwidSaveDynamicCss !== 'undefined' ) {
83
+ ecwidSaveDynamicCss();
84
+ }
85
+ });
86
+ }
87
+ }
88
+
89
+ var isTouchDevice = false;
90
+ var documentEventsForLazyLoading = ['mousedown', 'mouseup', 'mousemove', 'contextmenu', 'keydown', 'keyup'];
91
+ var documentTouchEventsForLazyLoading = ['touchstart', 'touchend', 'touchcancel', 'touchmove'];
92
+
93
+ if (!!('ontouchstart' in window)) {
94
+ isTouchDevice = true;
95
+ }
96
+
97
+ var toggleEvent = function (el, add, event) {
98
+ if (add) {
99
+ el.addEventListener(event, ecwidLazyScriptjsLoad);
100
+ } else {
101
+ el.removeEventListener(event, ecwidLazyScriptjsLoad);
102
+ }
103
+ }
104
+
105
+ if (isTouchDevice) {
106
+ documentTouchEventsForLazyLoading.forEach(
107
+ function applyEvent(event) {
108
+ toggleEvent(document, true, event);
109
+ }
110
+ );
111
+ } else {
112
+ documentEventsForLazyLoading.forEach(
113
+ function applyEvent(event) {
114
+ toggleEvent(document, true, event);
115
+ }
116
+ );
117
+ }
118
+ })();
119
+ </script>
120
+ <?php
121
+ }
122
+
123
+ public static function print_js_widget( $widget_type, $id, $arg = '' ) {
124
+ ob_start();
125
+
126
+ if ( self::is_enabled() ) {
127
+ $widget_type = preg_replace( '/^x([a-z0-9]+)/i', '$1', $widget_type );
128
+
129
+ if ( $widget_type === 'Search' ) {
130
+ $widget_type = 'SearchWidget';
131
+ }
132
+ ?>
133
+ <!--noptimize-->
134
+ <script data-cfasync="false" data-no-optimize="1" type="text/javascript">
135
+ window._xnext_initialization_scripts = window._xnext_initialization_scripts || [];
136
+ window._xnext_initialization_scripts.push({widgetType: '<?php echo esc_js( $widget_type ); ?>', id: '<?php echo esc_js( $id ); ?>', arg: [<?php echo $arg;//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>]});
137
+ </script>
138
+ <!--/noptimize-->
139
+ <?php
140
+ } else {
141
+ ?>
142
+ <!--noptimize--><script data-cfasync="false" data-no-optimize="1" type="text/javascript"><?php echo esc_js( $widget_type ); ?>();</script><!--/noptimize-->
143
+ <?php
144
+ }
145
+
146
+ return ob_get_clean();
147
+ }
148
+
149
+ }
150
+
151
+ $ec_store_defer_init = new Ec_Store_Defer_Init();
includes/class-ecwid-ajax-defer-renderer.php CHANGED
@@ -34,6 +34,7 @@ class Ecwid_Ajax_Defer_Renderer {
34
  add_filter( 'ecwid_disable_widgets', '__return_true' );
35
  add_filter( 'ecwid_shortcode_custom_renderer', array( $this, 'get_custom_renderer' ) );
36
  add_filter( 'the_content', array( $this, 'add_shortcodes' ) );
 
37
  $this->_already_enabled = true;
38
  }
39
  }
@@ -111,7 +112,8 @@ class Ecwid_Ajax_Defer_Renderer {
111
  if (typeof Ecwid != 'undefined' && Ecwid.destroy) Ecwid.destroy();
112
 
113
  if (typeof ecwid_shortcodes != 'undefined') {
114
- window._xnext_initialization_scripts = ecwid_shortcodes;
 
115
 
116
  if (!document.getElementById('ecwid-script')) {
117
  var script = document.createElement('script');
@@ -122,16 +124,6 @@ class Ecwid_Ajax_Defer_Renderer {
122
  script.setAttribute('data-cfasync', 'false');
123
 
124
  document.body.appendChild(script);
125
- var el = document.getElementById('ecwid-html-catalog-<?php echo esc_js( $ecwid_store_id ); ?>');
126
- if (el) {
127
- el.style.display = 'none';
128
- }
129
- if ( typeof Ecwid != 'undefined' ) {
130
- Ecwid.OnPageLoad.add(function() {
131
- var catalog = document.getElementById('ecwid-html-catalog-<?php echo esc_js( $ecwid_store_id ); ?>');
132
- catalog.parentElement.removeChild(catalog);
133
- });
134
- }
135
  } else {
136
  ecwid_onBodyDone();
137
  }
34
  add_filter( 'ecwid_disable_widgets', '__return_true' );
35
  add_filter( 'ecwid_shortcode_custom_renderer', array( $this, 'get_custom_renderer' ) );
36
  add_filter( 'the_content', array( $this, 'add_shortcodes' ) );
37
+ add_filter( 'ecwid_is_defer_store_init_enabled', '__return_false', 10000 );
38
  $this->_already_enabled = true;
39
  }
40
  }
112
  if (typeof Ecwid != 'undefined' && Ecwid.destroy) Ecwid.destroy();
113
 
114
  if (typeof ecwid_shortcodes != 'undefined') {
115
+ window._xnext_initialization_scripts = window._xnext_initialization_scripts || [];
116
+ window._xnext_initialization_scripts.push(...ecwid_shortcodes);
117
 
118
  if (!document.getElementById('ecwid-script')) {
119
  var script = document.createElement('script');
124
  script.setAttribute('data-cfasync', 'false');
125
 
126
  document.body.appendChild(script);
 
 
 
 
 
 
 
 
 
 
127
  } else {
128
  ecwid_onBodyDone();
129
  }
includes/class-ecwid-html-meta.php CHANGED
@@ -67,9 +67,11 @@ abstract class Ecwid_HTML_Meta {
67
  $store_id = get_ecwid_store_id();
68
  $params = ecwid_get_scriptjs_params();
69
 
70
- echo '<link rel="preload" href="https://' . Ecwid_Config::get_scriptjs_domain() . '/script.js?' . $store_id . $params . '" as="script">' . PHP_EOL; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
 
 
71
 
72
- if ( Ecwid_Static_Page::is_enabled_static_home_page() && Ecwid_Static_Page::is_data_available() ) {
73
  $css_files = Ecwid_Static_Page::get_css_files();
74
 
75
  if ( $css_files && is_array( $css_files ) ) {
@@ -240,7 +242,7 @@ class Ecwid_HTML_Meta_Other extends Ecwid_HTML_Meta {
240
 
241
  if ( $css_files && is_array( $css_files ) ) {
242
  foreach ( $css_files as $item ) {
243
- echo sprintf( '<link rel="prefetch" href="%s">', $item ) . PHP_EOL; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
244
  }
245
  }
246
  }
@@ -250,10 +252,10 @@ class Ecwid_HTML_Meta_Other extends Ecwid_HTML_Meta {
250
  $params = ecwid_get_scriptjs_params();
251
 
252
  $scriptjs_url = 'https://' . Ecwid_Config::get_scriptjs_domain() . '/script.js?' . $store_id . $params;
253
- echo sprintf( '<link rel="prefetch" href="%s" />', $scriptjs_url ) . PHP_EOL; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
254
 
255
  $page_url = Ecwid_Store_Page::get_store_url();
256
- echo sprintf( '<link rel="prerender" href="%s" />', $page_url ) . PHP_EOL; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
257
  }
258
  }
259
 
67
  $store_id = get_ecwid_store_id();
68
  $params = ecwid_get_scriptjs_params();
69
 
70
+ if ( ! Ec_Store_Defer_Init::is_enabled() || ! Ecwid_Static_Page::is_data_available() ) {
71
+ echo '<link rel="preload" href="https://' . Ecwid_Config::get_scriptjs_domain() . '/script.js?' . $store_id . $params . '" as="script">' . PHP_EOL; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
72
+ }
73
 
74
+ if ( Ecwid_Static_Page::is_enabled() && Ecwid_Static_Page::is_data_available() ) {
75
  $css_files = Ecwid_Static_Page::get_css_files();
76
 
77
  if ( $css_files && is_array( $css_files ) ) {
242
 
243
  if ( $css_files && is_array( $css_files ) ) {
244
  foreach ( $css_files as $item ) {
245
+ echo sprintf( '<link rel="prefetch" href="%s" as="style">', $item ) . PHP_EOL; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
246
  }
247
  }
248
  }
252
  $params = ecwid_get_scriptjs_params();
253
 
254
  $scriptjs_url = 'https://' . Ecwid_Config::get_scriptjs_domain() . '/script.js?' . $store_id . $params;
255
+ echo sprintf( '<link rel="prefetch" href="%s" as="script"/>', $scriptjs_url ) . PHP_EOL; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
256
 
257
  $page_url = Ecwid_Store_Page::get_store_url();
258
+ echo sprintf( '<link rel="prerender" href="%s"/>', $page_url ) . PHP_EOL; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
259
  }
260
  }
261
 
includes/class-ecwid-nav-menus.php CHANGED
@@ -155,7 +155,7 @@ class Ecwid_Nav_Menus {
155
  return;
156
  }
157
 
158
- wp_enqueue_script( 'ecwid-menu', ECWID_PLUGIN_URL . 'js/nav-menu-frontend.js', array( 'jquery' ), get_option( 'ecwid_plugin_version' ) );
159
  wp_localize_script(
160
  'ecwid-menu',
161
  'ecwid_menu_data',
155
  return;
156
  }
157
 
158
+ wp_enqueue_script( 'ecwid-menu', ECWID_PLUGIN_URL . 'js/nav-menu-frontend.js', array( 'jquery' ), get_option( 'ecwid_plugin_version' ), true );
159
  wp_localize_script(
160
  'ecwid-menu',
161
  'ecwid_menu_data',
includes/class-ecwid-products.php CHANGED
@@ -162,6 +162,7 @@ class Ecwid_Products {
162
  public function content( $content ) {
163
 
164
  if ( get_post_type() == self::POST_TYPE_PRODUCT ) {
 
165
 
166
  $ecwid_id = get_post_meta( get_the_ID(), 'ecwid_id' );
167
  $ecwid_id = $ecwid_id[0];
162
  public function content( $content ) {
163
 
164
  if ( get_post_type() == self::POST_TYPE_PRODUCT ) {
165
+ add_filter( 'ecwid_is_defer_store_init_enabled', '__return_false', 10000 );
166
 
167
  $ecwid_id = get_post_meta( get_the_ID(), 'ecwid_id' );
168
  $ecwid_id = $ecwid_id[0];
includes/class-ecwid-seo-links.php CHANGED
@@ -436,7 +436,7 @@ class Ecwid_Seo_Links {
436
  }
437
 
438
  protected function _build_all_base_urls() {
439
- $base_urls = array();
440
 
441
  $pages = Ecwid_Store_Page::get_store_pages_array();
442
 
436
  }
437
 
438
  protected function _build_all_base_urls() {
439
+ $base_urls = array();
440
 
441
  $pages = Ecwid_Store_Page::get_store_pages_array();
442
 
includes/class-ecwid-static-page.php CHANGED
@@ -11,14 +11,13 @@ class Ecwid_Static_Page {
11
  const HANDLE_STATIC_PAGE = 'static-page';
12
  const API_URL = 'https://storefront.ecwid.com/';
13
 
14
- protected $_has_theme_adjustments = false;
15
 
16
  public function __construct() {
17
  add_option( self::OPTION_IS_ENABLED );
18
 
19
  if ( ! is_admin() ) {
20
  add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
21
- add_action( Ecwid_Theme_Base::ACTION_APPLY_THEME, array( $this, 'apply_theme' ) );
22
  }
23
  }
24
 
@@ -35,34 +34,27 @@ class Ecwid_Static_Page {
35
  return null;
36
  }
37
 
38
- EcwidPlatform::enqueue_script( self::HANDLE_STATIC_PAGE, array() );
39
 
40
  $css_files = self::get_css_files();
41
 
42
  if ( $css_files && is_array( $css_files ) ) {
43
  foreach ( $css_files as $index => $item ) {
44
- wp_enqueue_style( 'ecwid-' . self::HANDLE_STATIC_PAGE . '-' . $index, $item, array(), null );
45
  }
46
  }
47
  }
48
 
49
- public function apply_theme( $theme ) {
50
- if ( $theme ) {
51
- $this->_has_theme_adjustments = true;
52
- }
53
- }
54
-
55
  public static function get_data_for_current_page() {
56
  if ( current_user_can( Ecwid_Admin::get_capability() ) ) {
57
  add_action( 'wp_enqueue_scripts', 'ecwid_enqueue_cache_control', 100 );
58
  }
59
 
60
- $data = self::_maybe_fetch_data();
61
-
62
  return $data;
63
  }
64
 
65
- protected static function _get_endpoint_url( $params = false ) {
66
 
67
  if ( ! $params ) {
68
  if ( ecwid_is_applicable_escaped_fragment() ) {
@@ -89,7 +81,7 @@ class Ecwid_Static_Page {
89
  return $url;
90
  }
91
 
92
- protected static function _maybe_fetch_data() {
93
  $version = get_bloginfo( 'version' );
94
  $pb_attribures = array();
95
  if ( strpos( $version, '5.0' ) === 0 || version_compare( $version, '5.0' ) > 0 ) {
@@ -106,18 +98,15 @@ class Ecwid_Static_Page {
106
  $params['base_url'] = get_permalink();
107
  }
108
 
109
- if ( array_key_exists( 'offset', $_GET ) ) {
110
- $params['offset'] = intval( $_GET['offset'] );
111
  }
112
 
113
- if ( ! array_key_exists( 'category', $_GET ) && isset( $store_page_params['default_category_id'] ) && $store_page_params['default_category_id'] > 0 ) {
114
  $params['default_category_id'] = $store_page_params['default_category_id'];
115
  }
116
 
117
- $http_accept_language = isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ? : '';
118
- $accept_language = apply_filters( 'ecwid_lang', $http_accept_language );
119
-
120
- $params['lang'] = $accept_language;
121
 
122
  $storefront_view_params = array( 'show_root_categories', 'enable_catalog_on_one_page' );
123
  foreach ( $storefront_view_params as $param ) {
@@ -133,8 +122,9 @@ class Ecwid_Static_Page {
133
 
134
  foreach ( $pb_attribures as $attribute ) {
135
  $name = $attribute['name'];
136
- if ( @$attribute['is_storefront_api'] && isset( $store_page_params[ $name ] ) ) {
137
- if ( @$attribute['type'] == 'boolean' ) {
 
138
  $value = $store_page_params[ $name ] ? 'true' : 'false';
139
  } else {
140
  $value = $store_page_params[ $name ];
@@ -147,12 +137,7 @@ class Ecwid_Static_Page {
147
  $params[ 'tplvar_ec.storefront.' . $name ] = $value;
148
  }
149
  }
150
- }
151
-
152
- if ( ! empty( $_COOKIE['ec_store_chameleon_font'] ) ) {
153
- $chameleon_cookie = sanitize_text_field( wp_unslash( $_COOKIE['ec_store_chameleon_font'] ) );
154
- $params['tplvar_ec.chameleon.font_family'] = stripslashes( $chameleon_cookie );
155
- }
156
 
157
  $hreflang_items = apply_filters( 'ecwid_hreflangs', null );
158
 
@@ -162,7 +147,7 @@ class Ecwid_Static_Page {
162
  }
163
  }
164
 
165
- $url = self::_get_endpoint_url( $endpoint_params );
166
 
167
  foreach ( $params as $name => $value ) {
168
  $url .= $name . '=' . rawurlencode( $value ) . '&';
@@ -170,46 +155,83 @@ class Ecwid_Static_Page {
170
 
171
  $url = substr( $url, 0, -1 );
172
 
173
- $cache_key = $url;
174
- $cached_data = EcwidPlatform::get_from_catalog_cache( $cache_key );
 
 
175
 
 
176
  if ( $cached_data ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  return $cached_data;
178
  }
179
 
180
- $fetched_data = null;
 
 
 
 
 
181
 
182
  $fetched_data = EcwidPlatform::fetch_url(
183
  $url,
184
  array(
185
  'timeout' => 3,
186
  'headers' => array(
187
- 'ACCEPT-LANGUAGE' => $accept_language,
188
  ),
189
  )
190
  );
191
 
192
- if ( $fetched_data && @$fetched_data['data'] ) {
 
 
 
 
 
 
 
 
 
 
193
 
194
- $fetched_data = @json_decode( $fetched_data['data'] );
 
195
 
196
  if ( isset( $fetched_data->lastUpdated ) ) {
197
  $last_update = substr( $fetched_data->lastUpdated, 0, -3 );
198
  } else {
199
  $last_update = time();
200
  }
 
201
 
202
  EcwidPlatform::invalidate_catalog_cache_from( $last_update );
203
-
204
- EcwidPlatform::store_in_catalog_cache( $cache_key, $fetched_data );
205
 
206
  return $fetched_data;
207
- }
208
 
209
  return null;
210
  }
211
 
212
- public static function _get_data_field( $field ) {
 
 
 
 
 
213
  $data = self::get_data_for_current_page();
214
 
215
  if ( isset( $data->$field ) ) {
@@ -221,23 +243,23 @@ class Ecwid_Static_Page {
221
  }
222
 
223
  public static function get_css_files() {
224
- return self::_get_data_field( 'cssFiles' );
225
  }
226
 
227
  public static function get_html_code() {
228
- return self::_get_data_field( 'htmlCode' );
229
  }
230
 
231
  public static function get_js_code() {
232
- return self::_get_data_field( 'jsCode' );
233
  }
234
 
235
  public static function get_title() {
236
- return self::_get_data_field( 'title' );
237
  }
238
 
239
  public static function get_meta_description_html() {
240
- $description = self::_get_data_field( 'metaDescriptionHtml' );
241
 
242
  if ( $description ) {
243
  $description = preg_replace( '/<title>.*?<\/title>/i', '', $description );
@@ -247,11 +269,11 @@ class Ecwid_Static_Page {
247
  }
248
 
249
  public static function get_canonical_url() {
250
- return self::_get_data_field( 'canonicalUrl' );
251
  }
252
 
253
  public static function get_og_tags_html() {
254
- $og_tags_html = self::_get_data_field( 'ogTagsHtml' );
255
 
256
  $ec_title = self::get_title();
257
  $wp_title = wp_get_document_title();
@@ -264,15 +286,15 @@ class Ecwid_Static_Page {
264
  }
265
 
266
  public static function get_json_ld_html() {
267
- return self::_get_data_field( 'jsonLDHtml' );
268
  }
269
 
270
  public static function get_href_lang_html() {
271
- return self::_get_data_field( 'hrefLangHtml' );
272
  }
273
 
274
  public static function get_last_update() {
275
- return self::_get_data_field( 'lastUpdated' );
276
  }
277
 
278
  public static function is_data_available() {
@@ -283,6 +305,10 @@ class Ecwid_Static_Page {
283
  return false;
284
  }
285
 
 
 
 
 
286
  public static function is_enabled_static_home_page() {
287
 
288
  $api = new Ecwid_Api_V3();
@@ -314,7 +340,7 @@ class Ecwid_Static_Page {
314
  return false;
315
  }
316
 
317
- if ( array_key_exists( 'ec-enable-static-page', $_GET ) ) {
318
  return true;
319
  }
320
 
@@ -326,7 +352,7 @@ class Ecwid_Static_Page {
326
  return false;
327
  }
328
 
329
- if ( get_option( self::OPTION_IS_ENABLED ) == self::OPTION_VALUE_ENABLED ) {
330
  return true;
331
  }
332
 
@@ -334,20 +360,16 @@ class Ecwid_Static_Page {
334
  return true;
335
  }
336
 
337
- if ( get_option( self::OPTION_IS_ENABLED ) == self::OPTION_VALUE_DISABLED ) {
338
  return false;
339
  }
340
 
341
- if ( get_option( self::OPTION_IS_ENABLED ) == '' ) {
342
  return true;
343
  }
344
 
345
  return false;
346
  }
347
-
348
- public static function is_feature_available() {
349
- return true;
350
- }
351
  }
352
 
353
  $__ecwid_static_page = new Ecwid_Static_Page();
11
  const HANDLE_STATIC_PAGE = 'static-page';
12
  const API_URL = 'https://storefront.ecwid.com/';
13
 
14
+ protected static $cache_key;
15
 
16
  public function __construct() {
17
  add_option( self::OPTION_IS_ENABLED );
18
 
19
  if ( ! is_admin() ) {
20
  add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
 
21
  }
22
  }
23
 
34
  return null;
35
  }
36
 
37
+ EcwidPlatform::enqueue_script( self::HANDLE_STATIC_PAGE, array(), true );
38
 
39
  $css_files = self::get_css_files();
40
 
41
  if ( $css_files && is_array( $css_files ) ) {
42
  foreach ( $css_files as $index => $item ) {
43
+ wp_enqueue_style( 'ecwid-' . self::HANDLE_STATIC_PAGE . '-' . $index, $item, array(), null ); //phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
44
  }
45
  }
46
  }
47
 
 
 
 
 
 
 
48
  public static function get_data_for_current_page() {
49
  if ( current_user_can( Ecwid_Admin::get_capability() ) ) {
50
  add_action( 'wp_enqueue_scripts', 'ecwid_enqueue_cache_control', 100 );
51
  }
52
 
53
+ $data = self::maybe_fetch_data();
 
54
  return $data;
55
  }
56
 
57
+ protected static function get_endpoint_url( $params = false ) {
58
 
59
  if ( ! $params ) {
60
  if ( ecwid_is_applicable_escaped_fragment() ) {
81
  return $url;
82
  }
83
 
84
+ protected static function maybe_fetch_data() {
85
  $version = get_bloginfo( 'version' );
86
  $pb_attribures = array();
87
  if ( strpos( $version, '5.0' ) === 0 || version_compare( $version, '5.0' ) > 0 ) {
98
  $params['base_url'] = get_permalink();
99
  }
100
 
101
+ if ( array_key_exists( 'offset', $_GET ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
102
+ $params['offset'] = intval( $_GET['offset'] ); //phpcs:ignore WordPress.Security.NonceVerification.Recommended
103
  }
104
 
105
+ if ( ! array_key_exists( 'category', $_GET ) && isset( $store_page_params['default_category_id'] ) && $store_page_params['default_category_id'] > 0 ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
106
  $params['default_category_id'] = $store_page_params['default_category_id'];
107
  }
108
 
109
+ $params['lang'] = self::get_accept_language();
 
 
 
110
 
111
  $storefront_view_params = array( 'show_root_categories', 'enable_catalog_on_one_page' );
112
  foreach ( $storefront_view_params as $param ) {
122
 
123
  foreach ( $pb_attribures as $attribute ) {
124
  $name = $attribute['name'];
125
+
126
+ if ( ! empty( $attribute['is_storefront_api'] ) && isset( $store_page_params[ $name ] ) ) {
127
+ if ( ! empty( $attribute['type'] ) && $attribute['type'] === 'boolean' ) {
128
  $value = $store_page_params[ $name ] ? 'true' : 'false';
129
  } else {
130
  $value = $store_page_params[ $name ];
137
  $params[ 'tplvar_ec.storefront.' . $name ] = $value;
138
  }
139
  }
140
+ }//end foreach
 
 
 
 
 
141
 
142
  $hreflang_items = apply_filters( 'ecwid_hreflangs', null );
143
 
147
  }
148
  }
149
 
150
+ $url = self::get_endpoint_url( $endpoint_params );
151
 
152
  foreach ( $params as $name => $value ) {
153
  $url .= $name . '=' . rawurlencode( $value ) . '&';
155
 
156
  $url = substr( $url, 0, -1 );
157
 
158
+ $dynamic_css = '';
159
+ if ( ! empty( $_COOKIE['ec_store_dynamic_css'] ) ) {
160
+ $dynamic_css = wp_strip_all_tags( $_COOKIE['ec_store_dynamic_css'] ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
161
+ }
162
 
163
+ $cached_data = EcwidPlatform::get_from_catalog_cache( $url );
164
  if ( $cached_data ) {
165
+
166
+ $is_css_defined = ! empty( $dynamic_css );
167
+ $is_css_already_set = ! empty( $cached_data->isSetDynamicCss ); //phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
168
+ $is_home_page = Ecwid_Store_Page::is_store_home_page();
169
+
170
+ if ( $is_home_page && $is_css_defined && ! $is_css_already_set ) {
171
+
172
+ $cached_data->cssFiles = array( $dynamic_css ); //phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
173
+ $cached_data->isSetDynamicCss = true; //phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
174
+
175
+ EcwidPlatform::store_in_catalog_cache( $url, $cached_data );
176
+ }
177
+
178
  return $cached_data;
179
  }
180
 
181
+ $fetched_data = self::get_static_snapshot( $url, $dynamic_css );
182
+
183
+ return $fetched_data;
184
+ }
185
+
186
+ protected static function get_static_snapshot( $url, $dynamic_css = '' ) {
187
 
188
  $fetched_data = EcwidPlatform::fetch_url(
189
  $url,
190
  array(
191
  'timeout' => 3,
192
  'headers' => array(
193
+ 'ACCEPT-LANGUAGE' => self::get_accept_language(),
194
  ),
195
  )
196
  );
197
 
198
+ if ( $fetched_data && isset( $fetched_data['data'] ) ) {
199
+ $fetched_data = json_decode( $fetched_data['data'] );
200
+
201
+ //phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
202
+ if ( ! empty( $dynamic_css ) ) {
203
+ $fetched_data->cssFiles = array( $dynamic_css );
204
+ $fetched_data->isSetDynamicCss = true;
205
+ }
206
+
207
+ if ( ! empty( $fetched_data->htmlCode ) ) {
208
+ $pattern = '/<img(.*?)>/is';
209
 
210
+ $fetched_data->htmlCode = preg_replace( $pattern, '<img $1 decoding="async" loading="lazy">', $fetched_data->htmlCode );
211
+ }
212
 
213
  if ( isset( $fetched_data->lastUpdated ) ) {
214
  $last_update = substr( $fetched_data->lastUpdated, 0, -3 );
215
  } else {
216
  $last_update = time();
217
  }
218
+ //phpcs:enable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
219
 
220
  EcwidPlatform::invalidate_catalog_cache_from( $last_update );
221
+ EcwidPlatform::store_in_catalog_cache( $url, $fetched_data );
 
222
 
223
  return $fetched_data;
224
+ }//end if
225
 
226
  return null;
227
  }
228
 
229
+ public static function get_accept_language() {
230
+ $http_accept_language = isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ? : ''; //phpcs:ignore Universal.Operators.DisallowShortTernary.Found
231
+ return apply_filters( 'ecwid_lang', $http_accept_language );
232
+ }
233
+
234
+ public static function get_data_field( $field ) {
235
  $data = self::get_data_for_current_page();
236
 
237
  if ( isset( $data->$field ) ) {
243
  }
244
 
245
  public static function get_css_files() {
246
+ return self::get_data_field( 'cssFiles' );
247
  }
248
 
249
  public static function get_html_code() {
250
+ return self::get_data_field( 'htmlCode' );
251
  }
252
 
253
  public static function get_js_code() {
254
+ return self::get_data_field( 'jsCode' );
255
  }
256
 
257
  public static function get_title() {
258
+ return self::get_data_field( 'title' );
259
  }
260
 
261
  public static function get_meta_description_html() {
262
+ $description = self::get_data_field( 'metaDescriptionHtml' );
263
 
264
  if ( $description ) {
265
  $description = preg_replace( '/<title>.*?<\/title>/i', '', $description );
269
  }
270
 
271
  public static function get_canonical_url() {
272
+ return self::get_data_field( 'canonicalUrl' );
273
  }
274
 
275
  public static function get_og_tags_html() {
276
+ $og_tags_html = self::get_data_field( 'ogTagsHtml' );
277
 
278
  $ec_title = self::get_title();
279
  $wp_title = wp_get_document_title();
286
  }
287
 
288
  public static function get_json_ld_html() {
289
+ return self::get_data_field( 'jsonLDHtml' );
290
  }
291
 
292
  public static function get_href_lang_html() {
293
+ return self::get_data_field( 'hrefLangHtml' );
294
  }
295
 
296
  public static function get_last_update() {
297
+ return self::get_data_field( 'lastUpdated' );
298
  }
299
 
300
  public static function is_data_available() {
305
  return false;
306
  }
307
 
308
+ public static function is_enabled() {
309
+ return self::is_enabled_static_home_page();
310
+ }
311
+
312
  public static function is_enabled_static_home_page() {
313
 
314
  $api = new Ecwid_Api_V3();
340
  return false;
341
  }
342
 
343
+ if ( array_key_exists( 'ec-enable-static-page', $_GET ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
344
  return true;
345
  }
346
 
352
  return false;
353
  }
354
 
355
+ if ( get_option( self::OPTION_IS_ENABLED ) === self::OPTION_VALUE_ENABLED ) {
356
  return true;
357
  }
358
 
360
  return true;
361
  }
362
 
363
+ if ( get_option( self::OPTION_IS_ENABLED ) === self::OPTION_VALUE_DISABLED ) {
364
  return false;
365
  }
366
 
367
+ if ( get_option( self::OPTION_IS_ENABLED ) === '' ) {
368
  return true;
369
  }
370
 
371
  return false;
372
  }
 
 
 
 
373
  }
374
 
375
  $__ecwid_static_page = new Ecwid_Static_Page();
includes/gutenberg/class-ecwid-gutenberg-block-minicart.php CHANGED
@@ -17,7 +17,7 @@ class Ecwid_Gutenberg_Block_Minicart extends Ecwid_Gutenberg_Block_Base {
17
 
18
  ob_start();
19
  ?>
20
- <!-- noptimize -->
21
  <?php
22
 
23
  echo ecwid_get_scriptjs_code(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
@@ -30,22 +30,22 @@ class Ecwid_Gutenberg_Block_Minicart extends Ecwid_Gutenberg_Block_Base {
30
  $params[ $param ] = $attributes[ $param ]['default'];
31
  }
32
  }
33
-
34
  ?>
35
-
36
  <div class='ec-cart-widget'
37
- data-fixed='false'
38
- data-fixed-shape='<?php echo esc_attr( @$params['fixed_shape'] ); ?>'
39
- data-layout='<?php echo esc_attr( @$params['layout'] ); ?>'
40
- data-icon='<?php echo esc_attr( @$params['icon'] ); ?>'
41
  ></div>
42
-
 
43
  <script>
44
  if (typeof Ecwid != 'undefined'){
45
  Ecwid.init();
46
  }
47
  </script>
48
- <!-- /noptimize -->
49
  <?php
50
 
51
  $contents = ob_get_contents();
17
 
18
  ob_start();
19
  ?>
20
+
21
  <?php
22
 
23
  echo ecwid_get_scriptjs_code(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
30
  $params[ $param ] = $attributes[ $param ]['default'];
31
  }
32
  }
 
33
  ?>
34
+
35
  <div class='ec-cart-widget'
36
+ data-fixed='false'
37
+ data-fixed-shape='<?php echo esc_attr( @$params['fixed_shape'] ); ?>'
38
+ data-layout='<?php echo esc_attr( @$params['layout'] ); ?>'
39
+ data-icon='<?php echo esc_attr( @$params['icon'] ); ?>'
40
  ></div>
41
+
42
+ <!--noptimize-->
43
  <script>
44
  if (typeof Ecwid != 'undefined'){
45
  Ecwid.init();
46
  }
47
  </script>
48
+ <!--/noptimize-->
49
  <?php
50
 
51
  $contents = ob_get_contents();
includes/integrations/class-ecwid-integration-above-the-fold.php DELETED
@@ -1,20 +0,0 @@
1
- <?php
2
-
3
- class Ecwid_Integration_Above_The_Fold
4
- {
5
- public function __construct()
6
- {
7
- add_filter( 'abtf_jsfile_pre', array( $this, 'filter_optimized_js' ) );
8
- }
9
-
10
- public function filter_optimized_js($file)
11
- {
12
- if ( strpos( $file, 'ecwid.com' ) !== false ) {
13
- return '';
14
- }
15
-
16
- return $file;
17
- }
18
- }
19
-
20
- $ecwid_integration_abtv = new Ecwid_Integration_Above_The_Fold();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/integrations/class-ecwid-integration-autoptimize.php CHANGED
@@ -1,28 +1,24 @@
1
  <?php
 
2
 
3
- class Ecwid_Integration_Autoptimize
4
- {
5
- public function __construct()
6
- {
7
  add_filter( 'ecwid_shortcode_content', array( $this, 'ecwid_shortcode_content' ) );
8
  add_filter( 'autoptimize_filter_js_exclude', array( $this, 'hook_js_exclude' ) );
9
  }
10
 
11
- public function ecwid_shortcode_content($content) {
12
- return '<!-- noptimize -->' . $content . '<!-- /noptimize -->';
13
  }
14
 
15
- public function hook_js_exclude($exclude) {
16
- $code= ecwid_get_search_js_code();
17
-
18
  $code .= ', ecwid_html, ecwid_body';
 
 
 
19
 
20
- $code .= ", " . Ecwid_Static_Page::HANDLE_STATIC_PAGE . ".js";
21
- $code .= ", EcStaticPageUtils";
22
- $code .= ", createClass";
23
-
24
- return $exclude . ", $code";
25
  }
26
  }
27
 
28
- $ecwid_integration_autoptimize = new Ecwid_Integration_Autoptimize();
1
  <?php
2
+ class Ecwid_Integration_Autoptimize {
3
 
4
+ public function __construct() {
 
 
 
5
  add_filter( 'ecwid_shortcode_content', array( $this, 'ecwid_shortcode_content' ) );
6
  add_filter( 'autoptimize_filter_js_exclude', array( $this, 'hook_js_exclude' ) );
7
  }
8
 
9
+ public function ecwid_shortcode_content( $content ) {
10
+ return '<!--noptimize-->' . $content . '<!--/noptimize-->';
11
  }
12
 
13
+ public function hook_js_exclude( $exclude ) {
14
+ $code = 'xSearch';
 
15
  $code .= ', ecwid_html, ecwid_body';
16
+ $code .= ', ' . Ecwid_Static_Page::HANDLE_STATIC_PAGE . '.js';
17
+ $code .= ', EcStaticPageUtils';
18
+ $code .= ', createClass';
19
 
20
+ return $exclude . ', ' . $code;
 
 
 
 
21
  }
22
  }
23
 
24
+ $ecwid_integration_autoptimize = new Ecwid_Integration_Autoptimize();
includes/shortcodes/class-ecwid-shortcode-base.php CHANGED
@@ -82,8 +82,8 @@ abstract class Ecwid_Shortcode_Base {
82
  $brand = Ecwid_Config::get_brand();
83
 
84
  $shortcode_content = "<!-- $brand shopping cart plugin v $version -->"
85
- . $shortcode_content
86
- . "<!-- END $brand Shopping Cart v $version -->";
87
 
88
  return $shortcode_content;
89
  }
@@ -111,14 +111,18 @@ abstract class Ecwid_Shortcode_Base {
111
 
112
  $function = $this->get_ecwid_widget_function_name();
113
 
114
- return sprintf( '<script data-cfasync="false" data-no-optimize="1" type="text/javascript">%s(%s);</script>', $function, $params_string );
 
 
 
 
115
  }
116
 
117
  public function render_placeholder() {
118
  $classname = $this->_get_html_class_name();
119
  $id = $this->get_html_id();
120
 
121
- return '<div class="ecwid-shopping-cart-' . esc_attr( $classname ) . ' id="' . esc_attr( $id ) . '"></div>';
122
  }
123
 
124
  protected function _get_html_class_name() {
82
  $brand = Ecwid_Config::get_brand();
83
 
84
  $shortcode_content = "<!-- $brand shopping cart plugin v $version -->"
85
+ . $shortcode_content
86
+ . "<!-- END $brand Shopping Cart v $version -->";
87
 
88
  return $shortcode_content;
89
  }
111
 
112
  $function = $this->get_ecwid_widget_function_name();
113
 
114
+ if ( ! Ec_Store_Defer_Init::is_enabled() ) {
115
+ return sprintf( '<script data-cfasync="false" data-no-optimize="1" type="text/javascript">%s(%s);</script>', $function, $params_string );
116
+ } else {
117
+ return Ec_Store_Defer_Init::print_js_widget( $function, $this->get_html_id(), $params_string );
118
+ }
119
  }
120
 
121
  public function render_placeholder() {
122
  $classname = $this->_get_html_class_name();
123
  $id = $this->get_html_id();
124
 
125
+ return '<div class="ecwid-shopping-cart-' . esc_attr( $classname ) . '" id="' . esc_attr( $id ) . '"></div>';
126
  }
127
 
128
  protected function _get_html_class_name() {
includes/shortcodes/class-ecwid-shortcode-minicart.php CHANGED
@@ -63,7 +63,7 @@ class Ecwid_Shortcode_Minicart extends Ecwid_Shortcode_Base {
63
  }
64
 
65
  $has_minicart = ( strpos( $default_render, 'xMinicart' ) !== false );
66
- if ( $has_minicart && Ecwid_Static_Page::is_enabled_static_home_page() && Ecwid_Static_Page::is_feature_available() ) {
67
  $default_render .= '<style>#static-ec-store { padding-top: 40px; }</style>';
68
  }
69
 
63
  }
64
 
65
  $has_minicart = ( strpos( $default_render, 'xMinicart' ) !== false );
66
+ if ( $has_minicart && Ecwid_Static_Page::is_enabled_static_home_page() ) {
67
  $default_render .= '<style>#static-ec-store { padding-top: 40px; }</style>';
68
  }
69
 
includes/shortcodes/class-ecwid-shortcode-productbrowser.php CHANGED
@@ -29,21 +29,64 @@ class Ecwid_Shortcode_ProductBrowser extends Ecwid_Shortcode_Base {
29
  $seo_links->check_base_urls_on_view_store_page_as_admin();
30
  }
31
 
32
- $default_render = parent::render();
33
-
34
  $option_print_html_catalog = get_option( 'ecwid_print_html_catalog', 'Y' );
35
 
36
  if ( ! Ecwid_Static_Page::is_data_available() || @$this->_params['noHTMLCatalog'] || empty( $option_print_html_catalog ) ) {
37
- $result = '<div id="dynamic-ec-store">' . $default_render . '</div>';
38
 
 
39
  if ( ! empty( $this->_params['default_page'] ) ) {
40
- $result .= $this->get_js_for_open_page( $this->_params['default_page'] );
41
  }
42
 
43
- return $result;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  }
45
 
46
- $code = '';
 
 
 
47
  global $ecwid_current_theme;
48
  if ( $ecwid_current_theme ) {
49
  ob_start();
@@ -58,31 +101,24 @@ class Ecwid_Shortcode_ProductBrowser extends Ecwid_Shortcode_Base {
58
  }
59
  </script>
60
  <?php
61
- $code = ob_get_clean();
62
- }
63
-
64
- $classname = '';
65
- if ( Ecwid_Static_Page::is_enabled_static_home_page() && Ecwid_Static_Page::is_feature_available() ) {
66
- $code .= self::_get_js_switch_dynamic( 'static-ec-store', 'dynamic-ec-store' );
67
- $classname = 'hide-ec-dynamic-placeholder';
68
- } else {
69
- $code .= self::_get_js_hide_static( '#static-ec-store' );
70
  }
 
 
71
 
72
- $code .= '<div id="dynamic-ec-store" class="' . $classname . '">' . $default_render . '</div>' . PHP_EOL;
73
 
74
- $static_html_code = Ecwid_Static_Page::get_html_code();
75
- $code .= '<div id="static-ec-store">' . htmlspecialchars_decode( $static_html_code ) . '</div>' . PHP_EOL;
 
76
 
77
- $js_code = Ecwid_Static_Page::get_js_code();
78
- if ( ! empty( $js_code ) ) {
79
- $code .= sprintf( '<script id="ec-static-inline-js" data-cfasync="false" data-no-optimize="1" type="text/javascript">%s</script>', $js_code ) . PHP_EOL;
80
- }
81
-
82
- return $code;
83
- }
84
 
85
- protected function _get_js_switch_dynamic( $static_container_id, $dynamic_container_id ) {
86
  ob_start();
87
  ?>
88
  <script data-cfasync="false" data-no-optimize="1" type="text/javascript">
@@ -93,12 +129,18 @@ class Ecwid_Shortcode_ProductBrowser extends Ecwid_Shortcode_Base {
93
  ec.storefront.staticPages.staticContainerID = '<?php echo esc_js( $static_container_id ); ?>';
94
  ec.storefront.staticPages.dynamicContainerID = '<?php echo esc_js( $dynamic_container_id ); ?>';
95
  ec.storefront.staticPages.autoSwitchStaticToDynamicWhenReady = true;
 
 
 
 
 
 
96
  </script>
97
  <?php
98
  return ob_get_clean();
99
  }
100
 
101
- protected function _get_js_hide_static( $html_selector ) {
102
  ob_start();
103
  ?>
104
  <script data-cfasync="false" data-no-optimize="1" type="text/javascript">
@@ -133,7 +175,7 @@ class Ecwid_Shortcode_ProductBrowser extends Ecwid_Shortcode_Base {
133
  $params['default_category_id'] = $this->_params['defaultCategoryId'];
134
  }
135
 
136
- if ( @$this->_params['defaultProductId'] ) {
137
  $params['default_product_id'] = $this->_params['defaultProductId'];
138
  }
139
 
@@ -141,7 +183,14 @@ class Ecwid_Shortcode_ProductBrowser extends Ecwid_Shortcode_Base {
141
 
142
  $classname = $this->_get_html_class_name();
143
 
144
- $result = '<div id="ecwid-store-' . $store_id . '" class="ecwid-shopping-cart-' . $classname . '" data-ecwid-default-category-id="' . $params['default_category_id'] . '"></div>';
 
 
 
 
 
 
 
145
 
146
  return $result;
147
  }
@@ -162,7 +211,7 @@ class Ecwid_Shortcode_ProductBrowser extends Ecwid_Shortcode_Base {
162
  );
163
 
164
  $grid = explode( ',', $atts['grid'] );
165
- if ( count( $grid ) == 2 ) {
166
  $atts['grid_rows'] = intval( $grid[0] );
167
  $atts['grid_cols'] = intval( $grid[1] );
168
  } else {
29
  $seo_links->check_base_urls_on_view_store_page_as_admin();
30
  }
31
 
 
 
32
  $option_print_html_catalog = get_option( 'ecwid_print_html_catalog', 'Y' );
33
 
34
  if ( ! Ecwid_Static_Page::is_data_available() || @$this->_params['noHTMLCatalog'] || empty( $option_print_html_catalog ) ) {
 
35
 
36
+ $code = self::get_dynamic_html_code();
37
  if ( ! empty( $this->_params['default_page'] ) ) {
38
+ $code .= $this->get_js_for_open_page( $this->_params['default_page'] );
39
  }
40
 
41
+ return $code;
42
+ }
43
+
44
+ $code = '';
45
+ $code .= self::get_js_for_adding_html_id();
46
+
47
+ $classname = '';
48
+ if ( Ecwid_Static_Page::is_enabled_static_home_page() ) {
49
+ add_filter( 'ecwid_hide_defer_load_script', '__return_true', 10000 );
50
+ $code .= self::get_js_for_switch_dynamic( 'static-ec-store-container', 'dynamic-ec-store-container' );
51
+ $classname = 'hide-ec-dynamic-placeholder';
52
+ } else {
53
+ add_filter( 'ecwid_is_defer_store_init_enabled', '__return_false', 10000 );
54
+ $code .= self::get_js_for_hide_static( '#static-ec-store-container' );
55
+ }
56
+
57
+ $code .= '<div id="static-ec-store-container">';
58
+ $code .= htmlspecialchars_decode( Ecwid_Static_Page::get_html_code() );
59
+
60
+ $js_code = Ecwid_Static_Page::get_js_code();
61
+ if ( ! empty( $js_code ) ) {
62
+ $code .= sprintf( '<script id="ec-static-inline-js" data-cfasync="false" data-no-optimize="1" type="text/javascript">%s</script>', $js_code ) . PHP_EOL;
63
+ }
64
+ $code .= '</div>';
65
+
66
+ $code .= self::get_dynamic_html_code( false, $classname );
67
+
68
+ $code .= '<script data-cfasync="false" data-no-optimize="1" type="text/javascript">
69
+ if( typeof window.ec.storefront.staticPages != "undefined" && typeof window.ec.storefront.staticPages.forceDynamicLoadingIfRequired != "undefined" ) {
70
+ window.ec.storefront.staticPages.forceDynamicLoadingIfRequired();
71
+ }
72
+ </script>';
73
+
74
+ return $code;
75
+ }
76
+
77
+ protected function get_dynamic_html_code( $is_default_render = true, $classname = '' ) {
78
+
79
+ if ( ! Ec_Store_Defer_Init::is_enabled() || $is_default_render ) {
80
+ $default_render = parent::render();
81
+ $code = '<div id="dynamic-ec-store-container" class="' . $classname . '">' . $default_render . '</div>' . PHP_EOL;
82
+ } else {
83
+ $code = '<div id="dynamic-ec-store-container"><div id="dynamic-ec-store"></div></div>' . PHP_EOL;
84
  }
85
 
86
+ return $code;
87
+ }
88
+
89
+ protected function get_js_for_adding_html_id() {
90
  global $ecwid_current_theme;
91
  if ( $ecwid_current_theme ) {
92
  ob_start();
101
  }
102
  </script>
103
  <?php
104
+ return ob_get_clean();
 
 
 
 
 
 
 
 
105
  }
106
+ return '';
107
+ }
108
 
109
+ protected function get_js_for_switch_dynamic( $static_container_id, $dynamic_container_id ) {
110
 
111
+ $store_id = get_ecwid_store_id();
112
+ $script_js_params = ecwid_get_scriptjs_params();
113
+ $script_js_link = 'https://' . Ecwid_Config::get_scriptjs_domain() . '/script.js?' . $store_id . $script_js_params;
114
 
115
+ $widget_params_string = $this->build_params_string(
116
+ array_merge(
117
+ $this->_params,
118
+ array( 'id' => 'dynamic-ec-store' )
119
+ )
120
+ );
 
121
 
 
122
  ob_start();
123
  ?>
124
  <script data-cfasync="false" data-no-optimize="1" type="text/javascript">
129
  ec.storefront.staticPages.staticContainerID = '<?php echo esc_js( $static_container_id ); ?>';
130
  ec.storefront.staticPages.dynamicContainerID = '<?php echo esc_js( $dynamic_container_id ); ?>';
131
  ec.storefront.staticPages.autoSwitchStaticToDynamicWhenReady = true;
132
+ <?php if ( Ec_Store_Defer_Init::is_enabled() ) { ?>
133
+ ec.storefront.staticPages.lazyLoading = {
134
+ scriptJsLink: '<?php echo $script_js_link; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>',
135
+ xProductBrowserArguments: [<?php echo $widget_params_string; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>]
136
+ }
137
+ <?php } ?>
138
  </script>
139
  <?php
140
  return ob_get_clean();
141
  }
142
 
143
+ protected function get_js_for_hide_static( $html_selector ) {
144
  ob_start();
145
  ?>
146
  <script data-cfasync="false" data-no-optimize="1" type="text/javascript">
175
  $params['default_category_id'] = $this->_params['defaultCategoryId'];
176
  }
177
 
178
+ if ( ! empty( $this->_params['defaultProductId'] ) ) {
179
  $params['default_product_id'] = $this->_params['defaultProductId'];
180
  }
181
 
183
 
184
  $classname = $this->_get_html_class_name();
185
 
186
+ $pb_placeholder = '';
187
+ if ( Ec_Store_Defer_Init::is_enabled() ) {
188
+ ob_start();
189
+ require ECWID_PLUGIN_DIR . '/templates/shortcode-pb-placeholder.php';
190
+ $pb_placeholder = ob_get_clean();
191
+ }
192
+
193
+ $result = '<div id="ecwid-store-' . $store_id . '" class="ecwid-shopping-cart-' . $classname . '" data-ecwid-default-category-id="' . $params['default_category_id'] . '">' . $pb_placeholder . '</div>';
194
 
195
  return $result;
196
  }
211
  );
212
 
213
  $grid = explode( ',', $atts['grid'] );
214
+ if ( count( $grid ) === 2 ) {
215
  $atts['grid_rows'] = intval( $grid[0] );
216
  $atts['grid_cols'] = intval( $grid[1] );
217
  } else {
includes/widgets.php CHANGED
@@ -37,7 +37,8 @@ function ecwid_sidebar_widgets_init() {
37
  register_widget( 'Ecwid_Widget_NSF_Minicart' );
38
  }
39
 
40
- $old_minicarts = array(
 
41
  'ecwidminicart_miniview' => 'Ecwid_Widget_Minicart_Miniview',
42
  'ecwidminicart' => 'Ecwid_Widget_Minicart',
43
  'ecwidfloatingshoppingcart' => 'Ecwid_Widget_Floating_Shopping_Cart',
@@ -46,9 +47,15 @@ function ecwid_sidebar_widgets_init() {
46
  foreach ( $old_minicarts as $idbase => $widget_class ) {
47
  if ( is_active_widget( false, false, $idbase ) || version_compare( get_bloginfo( 'version' ), '4.0' ) < 0 ) {
48
  register_widget( $widget_class );
 
 
49
  }
50
  }
51
 
 
 
 
 
52
  register_widget( 'Ecwid_Widget_Store_Link' );
53
 
54
  if ( Ecwid_Api_V3::is_available() ) {
37
  register_widget( 'Ecwid_Widget_NSF_Minicart' );
38
  }
39
 
40
+ $need_to_disable_defer_init = false;
41
+ $old_minicarts = array(
42
  'ecwidminicart_miniview' => 'Ecwid_Widget_Minicart_Miniview',
43
  'ecwidminicart' => 'Ecwid_Widget_Minicart',
44
  'ecwidfloatingshoppingcart' => 'Ecwid_Widget_Floating_Shopping_Cart',
47
  foreach ( $old_minicarts as $idbase => $widget_class ) {
48
  if ( is_active_widget( false, false, $idbase ) || version_compare( get_bloginfo( 'version' ), '4.0' ) < 0 ) {
49
  register_widget( $widget_class );
50
+
51
+ $need_to_disable_defer_init = true;
52
  }
53
  }
54
 
55
+ if ( $need_to_disable_defer_init ) {
56
+ add_filter( 'ecwid_is_defer_store_init_enabled', '__return_false', 10000 );
57
+ }
58
+
59
  register_widget( 'Ecwid_Widget_Store_Link' );
60
 
61
  if ( Ecwid_Api_V3::is_available() ) {
includes/widgets/class-ecwid-widget-base.php CHANGED
@@ -6,10 +6,17 @@ abstract class Ecwid_Widget_Base extends WP_Widget {
6
 
7
  abstract protected function _render_widget_content( $args, $instance );
8
 
 
 
 
 
9
  public function widget( $args, $instance ) {
 
 
 
 
10
 
11
- $before_widget = $before_title = $after_title = $after_widget = '';
12
- extract( $args );
13
 
14
  $renderer = apply_filters( 'ecwid_get_custom_widget_renderer', null );
15
 
6
 
7
  abstract protected function _render_widget_content( $args, $instance );
8
 
9
+ public function __construct( $id_base, $name, $widget_options = array(), $control_options = array() ) {
10
+ parent::__construct( $id_base, $name, $widget_options, $control_options );
11
+ }
12
+
13
  public function widget( $args, $instance ) {
14
+ $before_widget = '';
15
+ $before_title = '';
16
+ $after_title = '';
17
+ $after_widget = '';
18
 
19
+ extract( $args ); //phpcs:ignore WordPress.PHP.DontExtract.extract_extract
 
20
 
21
  $renderer = apply_filters( 'ecwid_get_custom_widget_renderer', null );
22
 
includes/widgets/class-ecwid-widget-floating-shopping-cart.php CHANGED
@@ -101,23 +101,26 @@ class Ecwid_Widget_Floating_Shopping_Cart extends Ecwid_Widget_Base {
101
  }
102
 
103
  ?>
104
- <!-- noptimize -->
105
  <?php echo ecwid_get_scriptjs_code(); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
106
  <div class="ecwid-float-icons position-<?php echo esc_attr( $position ); ?>" ondragstart="return false">
107
  <div class="ecwid-cart-icon off">
108
  <a href="<?php echo esc_url( $cart_url ); ?>" rel="nofollow" data-ecwid-page="cart" data-count="0">
109
  <svg width="20" height="26" viewBox="0 0 20 26" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 6.5v14.81c0 2.255 1.79 4.084 4 4.084h11c2.21 0 4-1.83 4-4.085V6.5H.5zM6 10.585c.552 0 1-.457 1-1.02C7 9 6.552 8.542 6 8.542S5 9 5 9.563c0 .565.448 1.022 1 1.022zm8 0c.552 0 1-.457 1-1.02 0-.565-.448-1.022-1-1.022S13 9 13 9.563c0 .565.448 1.022 1 1.022z" stroke="#439CA0"/><path d="M14.5 6h-1V4.582c0-1.97-1.57-3.575-3.5-3.575S6.5 2.61 6.5 4.582V6h-1V4.582C5.5 2.048 7.52-.014 10-.014c2.482 0 4.5 2.062 4.5 4.596V6z" fill="#439CA0"/></g></svg>
 
110
  <div id="ecwid-cart"><script type="text/javascript"> xMinicart("style=","id=ecwid-cart"); </script></div>
 
111
  </a>
112
  </div>
113
  </div>
 
114
  <script type="text/javascript">
115
  if (window.EcwidFloatingShoppingCart) {
116
  var ecwid_floating_shopping_cart = new EcwidFloatingShoppingCart();
117
  ecwid_floating_shopping_cart.init();
118
  }
119
  </script>
120
- <!-- /noptimize -->
121
  <?php
122
  }
123
 
101
  }
102
 
103
  ?>
104
+
105
  <?php echo ecwid_get_scriptjs_code(); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
106
  <div class="ecwid-float-icons position-<?php echo esc_attr( $position ); ?>" ondragstart="return false">
107
  <div class="ecwid-cart-icon off">
108
  <a href="<?php echo esc_url( $cart_url ); ?>" rel="nofollow" data-ecwid-page="cart" data-count="0">
109
  <svg width="20" height="26" viewBox="0 0 20 26" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><path d="M.5 6.5v14.81c0 2.255 1.79 4.084 4 4.084h11c2.21 0 4-1.83 4-4.085V6.5H.5zM6 10.585c.552 0 1-.457 1-1.02C7 9 6.552 8.542 6 8.542S5 9 5 9.563c0 .565.448 1.022 1 1.022zm8 0c.552 0 1-.457 1-1.02 0-.565-.448-1.022-1-1.022S13 9 13 9.563c0 .565.448 1.022 1 1.022z" stroke="#439CA0"/><path d="M14.5 6h-1V4.582c0-1.97-1.57-3.575-3.5-3.575S6.5 2.61 6.5 4.582V6h-1V4.582C5.5 2.048 7.52-.014 10-.014c2.482 0 4.5 2.062 4.5 4.596V6z" fill="#439CA0"/></g></svg>
110
+ <!--noptimize-->
111
  <div id="ecwid-cart"><script type="text/javascript"> xMinicart("style=","id=ecwid-cart"); </script></div>
112
+ <!--/noptimize-->
113
  </a>
114
  </div>
115
  </div>
116
+ <!--noptimize-->
117
  <script type="text/javascript">
118
  if (window.EcwidFloatingShoppingCart) {
119
  var ecwid_floating_shopping_cart = new EcwidFloatingShoppingCart();
120
  ecwid_floating_shopping_cart.init();
121
  }
122
  </script>
123
+ <!--/noptimize-->
124
  <?php
125
  }
126
 
includes/widgets/class-ecwid-widget-latest-products.php CHANGED
@@ -1,13 +1,13 @@
1
  <?php
2
 
3
- require_once dirname(__FILE__) . '/class-ecwid-widget-products-base.php';
4
 
5
  class Ecwid_Widget_Latest_Products extends Ecwid_Widget_Products_List_Base {
6
 
7
  public function __construct() {
8
  $this->_init(
9
- __('Latest Products', 'ecwid-shopping-cart'),
10
- __('Displays the latest added products from your store. Show new products to returning customers to drive repeat sales.', 'ecwid-shopping-cart'),
11
  'ecwidlatestproducts'
12
  );
13
 
@@ -16,13 +16,14 @@ class Ecwid_Widget_Latest_Products extends Ecwid_Widget_Products_List_Base {
16
 
17
  protected function _get_products() {
18
  $api = new Ecwid_Api_V3();
19
-
20
-
21
- $result = $api->search_products(array(
22
- 'sortBy' => 'ADDED_TIME_DESC',
23
- 'limit' => $this->_instance['number_of_products']
24
- ));
25
-
 
26
  return @$result->items;
27
  }
28
  }
1
  <?php
2
 
3
+ require_once dirname( __FILE__ ) . '/class-ecwid-widget-products-base.php';
4
 
5
  class Ecwid_Widget_Latest_Products extends Ecwid_Widget_Products_List_Base {
6
 
7
  public function __construct() {
8
  $this->_init(
9
+ __( 'Latest Products', 'ecwid-shopping-cart' ),
10
+ __( 'Displays the latest added products from your store. Show new products to returning customers to drive repeat sales.', 'ecwid-shopping-cart' ),
11
  'ecwidlatestproducts'
12
  );
13
 
16
 
17
  protected function _get_products() {
18
  $api = new Ecwid_Api_V3();
19
+
20
+ $result = $api->search_products(
21
+ array(
22
+ 'sortBy' => 'ADDED_TIME_DESC',
23
+ 'limit' => $this->_instance['number_of_products'],
24
+ )
25
+ );
26
+
27
  return @$result->items;
28
  }
29
  }
includes/widgets/class-ecwid-widget-minicart-miniview.php CHANGED
@@ -4,7 +4,7 @@ require_once ECWID_PLUGIN_DIR . '/includes/widgets/class-ecwid-widget-base.php';
4
 
5
  class Ecwid_Widget_Minicart_Miniview extends Ecwid_Widget_Base {
6
 
7
- function __construct() {
8
  $widget_ops = array(
9
  'classname' => 'widget_ecwid_minicart_miniview',
10
  'description' => __( 'Adds a compact cart widget for customer to see the products they added to the cart.', 'ecwid-shopping-cart' ),
@@ -12,31 +12,25 @@ class Ecwid_Widget_Minicart_Miniview extends Ecwid_Widget_Base {
12
  parent::__construct( 'ecwidminicart_miniview', __( 'Shopping Cart Mini (deprecated)', 'ecwid-shopping-cart' ), $widget_ops );
13
  }
14
 
15
- function _render_widget_content( $args, $instance ) {
16
-
17
- $html = '';
18
-
19
- $html .= '<div>';
20
- $html .= '<!-- noptimize -->';
21
 
 
22
  $html .= ecwid_get_scriptjs_code();
23
  $html .= ecwid_get_product_browser_url_script();
24
- $html .= '<script data-cfasync="false" type="text/javascript"> xMinicart("style=left:10px","layout=Mini"); </script>';
25
-
26
- $html .= '<!-- /noptimize -->';
27
  $html .= '</div>';
28
 
29
  return $html;
30
  }
31
 
32
- function update( $new_instance, $old_instance ) {
33
  $instance = $old_instance;
34
- $instance['title'] = strip_tags( stripslashes( $new_instance['title'] ) );
35
 
36
  return $instance;
37
  }
38
 
39
- function form( $instance ) {
40
  $instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
41
 
42
  $title = htmlspecialchars( $instance['title'] );
4
 
5
  class Ecwid_Widget_Minicart_Miniview extends Ecwid_Widget_Base {
6
 
7
+ public function __construct() {
8
  $widget_ops = array(
9
  'classname' => 'widget_ecwid_minicart_miniview',
10
  'description' => __( 'Adds a compact cart widget for customer to see the products they added to the cart.', 'ecwid-shopping-cart' ),
12
  parent::__construct( 'ecwidminicart_miniview', __( 'Shopping Cart Mini (deprecated)', 'ecwid-shopping-cart' ), $widget_ops );
13
  }
14
 
15
+ public function _render_widget_content( $args, $instance ) {
 
 
 
 
 
16
 
17
+ $html = '<div>';
18
  $html .= ecwid_get_scriptjs_code();
19
  $html .= ecwid_get_product_browser_url_script();
20
+ $html .= '<!--noptimize--><script data-cfasync="false" type="text/javascript"> xMinicart("style=left:10px","layout=Mini"); </script><!--/noptimize-->';
 
 
21
  $html .= '</div>';
22
 
23
  return $html;
24
  }
25
 
26
+ public function update( $new_instance, $old_instance ) {
27
  $instance = $old_instance;
28
+ $instance['title'] = wp_strip_all_tags( stripslashes( $new_instance['title'] ) );
29
 
30
  return $instance;
31
  }
32
 
33
+ public function form( $instance ) {
34
  $instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
35
 
36
  $title = htmlspecialchars( $instance['title'] );
includes/widgets/class-ecwid-widget-minicart.php CHANGED
@@ -4,39 +4,33 @@ require_once ECWID_PLUGIN_DIR . '/includes/widgets/class-ecwid-widget-base.php';
4
 
5
  class Ecwid_Widget_Minicart extends Ecwid_Widget_Base {
6
 
7
- function __construct() {
8
  $widget_ops = array(
9
  'classname' => 'widget_ecwid_minicart',
10
  'description' => __( 'Adds a cart widget for customer to see the products they added to the cart.', 'ecwid-shopping-cart' ),
11
  );
12
  parent::__construct( 'ecwidminicart', __( 'Shopping Cart (deprecated)', 'ecwid-shopping-cart' ), $widget_ops );
13
-
14
  }
15
 
16
- function _render_widget_content( $args, $instance ) {
17
-
18
- $html = '';
19
- echo '<div>';
20
 
21
- $html .= '<!-- noptimize -->';
22
  $html .= ecwid_get_scriptjs_code();
23
  $html .= ecwid_get_product_browser_url_script();
24
- $html .= '<script data-cfasync="false" type="text/javascript"> xMinicart("style="); </script>';
25
-
26
- $html .= '<!-- /noptimize -->';
27
  $html .= '</div>';
28
 
29
  return $html;
30
  }
31
 
32
- function update( $new_instance, $old_instance ) {
33
  $instance = $old_instance;
34
- $instance['title'] = strip_tags( stripslashes( $new_instance['title'] ) );
35
 
36
  return $instance;
37
  }
38
 
39
- function form( $instance ) {
40
  $instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
41
 
42
  $title = htmlspecialchars( $instance['title'] );
4
 
5
  class Ecwid_Widget_Minicart extends Ecwid_Widget_Base {
6
 
7
+ public function __construct() {
8
  $widget_ops = array(
9
  'classname' => 'widget_ecwid_minicart',
10
  'description' => __( 'Adds a cart widget for customer to see the products they added to the cart.', 'ecwid-shopping-cart' ),
11
  );
12
  parent::__construct( 'ecwidminicart', __( 'Shopping Cart (deprecated)', 'ecwid-shopping-cart' ), $widget_ops );
 
13
  }
14
 
15
+ public function _render_widget_content( $args, $instance ) {
 
 
 
16
 
17
+ $html = '<div>';
18
  $html .= ecwid_get_scriptjs_code();
19
  $html .= ecwid_get_product_browser_url_script();
20
+ $html .= '<!--noptimize--><script data-cfasync="false" type="text/javascript"> xMinicart("style="); </script><!--/noptimize-->';
 
 
21
  $html .= '</div>';
22
 
23
  return $html;
24
  }
25
 
26
+ public function update( $new_instance, $old_instance ) {
27
  $instance = $old_instance;
28
+ $instance['title'] = wp_strip_all_tags( stripslashes( $new_instance['title'] ) );
29
 
30
  return $instance;
31
  }
32
 
33
+ public function form( $instance ) {
34
  $instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
35
 
36
  $title = htmlspecialchars( $instance['title'] );
includes/widgets/class-ecwid-widget-products-base.php CHANGED
@@ -65,7 +65,7 @@ abstract class Ecwid_Widget_Products_List_Base extends Ecwid_Widget_Base {
65
  $this->_instance = wp_parse_args( $instance, array( 'number_of_products' => $this->_default ) );
66
 
67
  $html = '';
68
- $html .= '<!-- noptimize -->' . ecwid_get_scriptjs_code() . '<!-- /noptimize -->';
69
 
70
  $html .= '<div class="' . $this->_class_name . '" data-ecwid-max="' . $this->_instance['number_of_products'] . '">';
71
 
@@ -116,21 +116,22 @@ abstract class Ecwid_Widget_Products_List_Base extends Ecwid_Widget_Base {
116
  }
117
 
118
  $force_image = '';
119
- if ( isset( $product->imageUrl ) && strpos( $product->imageUrl, 'https://' ) == 0 ) {
120
- $force_image = $product->imageUrl;
121
  }
122
 
123
  $name = esc_html( $product->name );
124
  $price = $product->price;
125
 
 
126
  ?>
127
  <a class="product" href="<?php echo esc_url( $product->link ); ?>" data-ecwid-product-id="<?php echo esc_attr( $product->id ); ?>" alt="<?php echo esc_attr( $name ); ?>" title="<?php echo esc_attr( $name ); ?>" data-ecwid-page="product">
128
- <div class="ecwid ecwid-SingleProduct ecwid-Product ecwid-Product-<?php echo esc_attr( $product->id ); ?>" data-single-product-link="<?php echo esc_url( $product->link ); ?>" data-single-product-id="<?php echo esc_attr( $product->id ); ?>" itemscope itemtype="http://schema.org/Product">
129
  <div itemprop="image" data-force-image="<?php echo esc_attr( $force_image ); ?>"></div>
130
  <div class="ecwid-title" itemprop="name" content="<?php echo esc_attr( $name ); ?>"></div>
131
  <div itemtype="http://schema.org/Offer" itemscope itemprop="offers"><div class="ecwid-productBrowser-price ecwid-price" itemprop="price" content="<?php echo esc_attr( $price ); ?>"></div></div>
132
  </div>
133
- <!-- noptimize --><script type="text/javascript">xSingleProduct();</script><!-- /noptimize -->
134
  </a>
135
  <?php
136
  $next++;
65
  $this->_instance = wp_parse_args( $instance, array( 'number_of_products' => $this->_default ) );
66
 
67
  $html = '';
68
+ $html .= ecwid_get_scriptjs_code();
69
 
70
  $html .= '<div class="' . $this->_class_name . '" data-ecwid-max="' . $this->_instance['number_of_products'] . '">';
71
 
116
  }
117
 
118
  $force_image = '';
119
+ if ( isset( $product->imageUrl ) && strpos( $product->imageUrl, 'https://' ) == 0 ) {//phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
120
+ $force_image = $product->imageUrl; //phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
121
  }
122
 
123
  $name = esc_html( $product->name );
124
  $price = $product->price;
125
 
126
+ $widget_id = 'ec-store-widget-product-' . $product->id;
127
  ?>
128
  <a class="product" href="<?php echo esc_url( $product->link ); ?>" data-ecwid-product-id="<?php echo esc_attr( $product->id ); ?>" alt="<?php echo esc_attr( $name ); ?>" title="<?php echo esc_attr( $name ); ?>" data-ecwid-page="product">
129
+ <div class="ecwid ecwid-SingleProduct ecwid-Product ecwid-Product-<?php echo esc_attr( $product->id ); ?>" data-single-product-link="<?php echo esc_url( $product->link ); ?>" data-single-product-id="<?php echo esc_attr( $product->id ); ?>" itemscope itemtype="http://schema.org/Product" id="<?php echo esc_attr( $widget_id ); ?>">
130
  <div itemprop="image" data-force-image="<?php echo esc_attr( $force_image ); ?>"></div>
131
  <div class="ecwid-title" itemprop="name" content="<?php echo esc_attr( $name ); ?>"></div>
132
  <div itemtype="http://schema.org/Offer" itemscope itemprop="offers"><div class="ecwid-productBrowser-price ecwid-price" itemprop="price" content="<?php echo esc_attr( $price ); ?>"></div></div>
133
  </div>
134
+ <?php echo Ec_Store_Defer_Init::print_js_widget( 'xSingleProduct', $widget_id );//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
135
  </a>
136
  <?php
137
  $next++;
includes/widgets/class-ecwid-widget-random-product.php CHANGED
@@ -10,7 +10,6 @@ class Ecwid_Widget_Random_Product extends Ecwid_Widget_Base {
10
  'description' => __( 'Displays a random product from your store to attract customer attention.', 'ecwid-shopping-cart' ),
11
  );
12
  parent::__construct( 'ecwidrandomproduct', __( 'Random Product', 'ecwid-shopping-cart' ), $widget_ops );
13
-
14
  }
15
 
16
  protected function _render_widget_content( $args, $instance ) {
@@ -20,30 +19,32 @@ class Ecwid_Widget_Random_Product extends Ecwid_Widget_Base {
20
  return '';
21
  }
22
 
23
- $name = esc_attr( $product->name );
24
-
25
- $url = $product->link;
26
 
27
  $content = "<div class='ecwid ecwid-random-product ecwid-SingleProduct-v2 ecwid-SingleProduct-v2-bordered ecwid-SingleProduct-v2-centered ecwid-Product ecwid-Product-$product->id' itemscope itemtype='http://schema.org/Product' data-single-product-id='$product->id'>
28
- <a href='$url' data-ecwid-page='product' data-ecwid-product-id='$product->id'><div itemprop='image'></div></a>
29
- <a href='$url' data-ecwid-page='product' data-ecwid-product-id='$product->id'><div class='ecwid-title' itemprop='name' content='$name'></div></a>
30
- <a href='$url' data-ecwid-page='product' data-ecwid-product-id='$product->id'><div itemtype='http://schema.org/Offer' itemscope itemprop='offers'>
31
- <div class='ecwid-productBrowser-price ecwid-price' itemprop='price' content='$product->defaultDisplayedPrice' data-spw-price-location='button'>
32
- <div itemprop='priceCurrency'></div>
33
- </div>
34
- </div>
35
- </a>
36
- </div>
37
- <script type='text/javascript'>xProduct()</script>";
 
 
 
 
38
 
39
  $html = '';
40
  $html .= '<div>';
41
 
42
- $html .= '<!-- noptimize -->';
43
  $html .= ecwid_get_scriptjs_code();
44
  $html .= $content;
45
 
46
- $html .= '<!-- /noptimize -->';
47
  $html .= '</div>';
48
 
49
  return $html;
10
  'description' => __( 'Displays a random product from your store to attract customer attention.', 'ecwid-shopping-cart' ),
11
  );
12
  parent::__construct( 'ecwidrandomproduct', __( 'Random Product', 'ecwid-shopping-cart' ), $widget_ops );
 
13
  }
14
 
15
  protected function _render_widget_content( $args, $instance ) {
19
  return '';
20
  }
21
 
22
+ $name = esc_attr( $product->name );
23
+ $url = $product->link;
24
+ $widget_id = 'ec-store-widget-random-' . $product->id;
25
 
26
  $content = "<div class='ecwid ecwid-random-product ecwid-SingleProduct-v2 ecwid-SingleProduct-v2-bordered ecwid-SingleProduct-v2-centered ecwid-Product ecwid-Product-$product->id' itemscope itemtype='http://schema.org/Product' data-single-product-id='$product->id'>
27
+ <div id='$widget_id'>
28
+ <a href='$url' data-ecwid-page='product' data-ecwid-product-id='$product->id'><div itemprop='image'></div></a>
29
+ <a href='$url' data-ecwid-page='product' data-ecwid-product-id='$product->id'><div class='ecwid-title' itemprop='name' content='$name'></div></a>
30
+ <a href='$url' data-ecwid-page='product' data-ecwid-product-id='$product->id'>
31
+ <div itemtype='http://schema.org/Offer' itemscope itemprop='offers'>
32
+ <div class='ecwid-productBrowser-price ecwid-price' itemprop='price' content='$product->defaultDisplayedPrice' data-spw-price-location='button'>
33
+ <div itemprop='priceCurrency'></div>
34
+ </div>
35
+ </div>
36
+ </a>
37
+ </div>
38
+ </div>";
39
+
40
+ $content .= Ec_Store_Defer_Init::print_js_widget( 'xProduct', $widget_id );
41
 
42
  $html = '';
43
  $html .= '<div>';
44
 
 
45
  $html .= ecwid_get_scriptjs_code();
46
  $html .= $content;
47
 
 
48
  $html .= '</div>';
49
 
50
  return $html;
includes/widgets/class-ecwid-widget-random-products.php DELETED
@@ -1,58 +0,0 @@
1
- <?php
2
-
3
- require_once dirname(__FILE__) . '/class-ecwid-widget-products-base.php';
4
-
5
- class Ecwid_Widget_Random_Products extends Ecwid_Widget_Products_List_Base {
6
-
7
- public function __construct() {
8
- $this->_init(
9
- __('Random Products', 'ecwid-shopping-cart'),
10
- __('Displays a list of random products.', 'ecwid-shopping-cart')
11
- );
12
-
13
- parent::__construct();
14
- }
15
-
16
- protected function _get_products() {
17
- $api = new Ecwid_Api_V3();
18
-
19
- $sorts = array(
20
- 'PRICE_ASC',
21
- 'ADDED_TIME_ASC',
22
- 'UPDATED_TIME_ASC',
23
- 'NAME_ASC'
24
- );
25
-
26
- $total = EcwidPlatform::get_from_products_cache('ecwid_total_products');
27
-
28
- $offset = 0;
29
- if ($total > 0) {
30
- $max = $total / 100;
31
- $offset = rand(0, $max - 1) * 100;
32
- }
33
-
34
-
35
- $found = $api->search_products(array(
36
- 'sortBy' => $sorts[rand(0, 3)],
37
- 'offset' => $offset
38
- ));
39
-
40
- $items = $found->items;
41
-
42
- $result = array();
43
- for ($i = 0; $i < $this->_instance['number_of_products']; $i++) {
44
-
45
- if (count($items) == 0) {
46
- break;
47
- }
48
-
49
- $ind = rand(0, count($items) - 1);
50
-
51
- $result[] = $items[$ind];
52
- unset($items[$ind]);
53
- $items = array_values($items);
54
- }
55
-
56
- return $result;
57
- }
58
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/widgets/class-ecwid-widget-search.php CHANGED
@@ -8,7 +8,7 @@ class Ecwid_Widget_Search extends Ecwid_Widget_Base {
8
  return is_active_widget( false, false, 'ecwidsearch' );
9
  }
10
 
11
- function __construct() {
12
  $widget_ops = array(
13
  'classname' => 'widget_ecwid_search',
14
  'description' => __( 'Displays a simple search box for your customers to find a product in your store', 'ecwid-shopping-cart' ),
@@ -16,32 +16,31 @@ class Ecwid_Widget_Search extends Ecwid_Widget_Base {
16
  parent::__construct( 'ecwidsearch', __( 'Product Search', 'ecwid-shopping-cart' ), $widget_ops );
17
  }
18
 
19
- function _render_widget_content( $args, $instance ) {
 
 
20
 
21
  $html = '';
22
- $html .= '<div>';
23
- $html .= '<!-- noptimize -->';
24
 
25
  $html .= ecwid_get_scriptjs_code();
26
  $html .= ecwid_get_product_browser_url_script();
27
 
28
- $code = ecwid_get_search_js_code();
29
- $html .= '<script data-cfasync="false" type="text/javascript"> ' . $code . ' </script>';
30
 
31
- $html .= '<!-- /noptimize -->';
32
  $html .= '</div>';
33
 
34
  return $html;
35
  }
36
 
37
- function update( $new_instance, $old_instance ) {
38
  $instance = $old_instance;
39
- $instance['title'] = strip_tags( stripslashes( $new_instance['title'] ) );
40
 
41
  return $instance;
42
  }
43
 
44
- function form( $instance ) {
45
  $instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
46
 
47
  $title = htmlspecialchars( $instance['title'] );
8
  return is_active_widget( false, false, 'ecwidsearch' );
9
  }
10
 
11
+ public function __construct() {
12
  $widget_ops = array(
13
  'classname' => 'widget_ecwid_search',
14
  'description' => __( 'Displays a simple search box for your customers to find a product in your store', 'ecwid-shopping-cart' ),
16
  parent::__construct( 'ecwidsearch', __( 'Product Search', 'ecwid-shopping-cart' ), $widget_ops );
17
  }
18
 
19
+ public function _render_widget_content( $args, $instance ) {
20
+
21
+ $widget_id = 'ec-store-search-' . $this->id_base;
22
 
23
  $html = '';
24
+ $html .= '<div id="' . $widget_id . '">';
 
25
 
26
  $html .= ecwid_get_scriptjs_code();
27
  $html .= ecwid_get_product_browser_url_script();
28
 
29
+ $html .= Ec_Store_Defer_Init::print_js_widget( 'xSearch', $widget_id );
 
30
 
 
31
  $html .= '</div>';
32
 
33
  return $html;
34
  }
35
 
36
+ public function update( $new_instance, $old_instance ) {
37
  $instance = $old_instance;
38
+ $instance['title'] = wp_strip_all_tags( stripslashes( $new_instance['title'] ) );
39
 
40
  return $instance;
41
  }
42
 
43
+ public function form( $instance ) {
44
  $instance = wp_parse_args( (array) $instance, array( 'title' => '' ) );
45
 
46
  $title = htmlspecialchars( $instance['title'] );
includes/widgets/class-ecwid-widget-store-link.php CHANGED
@@ -4,7 +4,7 @@ require_once ECWID_PLUGIN_DIR . '/includes/widgets/class-ecwid-widget-base.php';
4
 
5
  class Ecwid_Widget_Store_Link extends Ecwid_Widget_Base {
6
 
7
- function __construct() {
8
  $this->_hide_title = true;
9
  $widget_ops = array(
10
  'classname' => 'widget_ecwid_store_link',
@@ -13,7 +13,7 @@ class Ecwid_Widget_Store_Link extends Ecwid_Widget_Base {
13
  parent::__construct( 'ecwidstorelink', __( 'Store Page Link', 'ecwid-shopping-cart' ), $widget_ops );
14
  }
15
 
16
- function _render_widget_content( $args, $instance ) {
17
 
18
  $html = '<div>';
19
 
@@ -23,14 +23,14 @@ class Ecwid_Widget_Store_Link extends Ecwid_Widget_Base {
23
  return $html;
24
  }
25
 
26
- function update( $new_instance, $old_instance ) {
27
  $instance = $old_instance;
28
- $instance['label'] = strip_tags( stripslashes( $new_instance['label'] ) );
29
 
30
  return $instance;
31
  }
32
 
33
- function form( $instance ) {
34
  $instance = wp_parse_args( (array) $instance, array( 'label' => __( 'Shop', 'ecwid-shopping-cart' ) ) );
35
 
36
  $label = htmlspecialchars( $instance['label'] );
4
 
5
  class Ecwid_Widget_Store_Link extends Ecwid_Widget_Base {
6
 
7
+ public function __construct() {
8
  $this->_hide_title = true;
9
  $widget_ops = array(
10
  'classname' => 'widget_ecwid_store_link',
13
  parent::__construct( 'ecwidstorelink', __( 'Store Page Link', 'ecwid-shopping-cart' ), $widget_ops );
14
  }
15
 
16
+ public function _render_widget_content( $args, $instance ) {
17
 
18
  $html = '<div>';
19
 
23
  return $html;
24
  }
25
 
26
+ public function update( $new_instance, $old_instance ) {
27
  $instance = $old_instance;
28
+ $instance['label'] = wp_strip_all_tags( stripslashes( $new_instance['label'] ) );
29
 
30
  return $instance;
31
  }
32
 
33
+ public function form( $instance ) {
34
  $instance = wp_parse_args( (array) $instance, array( 'label' => __( 'Shop', 'ecwid-shopping-cart' ) ) );
35
 
36
  $label = htmlspecialchars( $instance['label'] );
includes/widgets/class-ecwid-widget-vcategories.php CHANGED
@@ -15,13 +15,9 @@ class Ecwid_Widget_VCategories extends Ecwid_Widget_Base {
15
  function _render_widget_content( $args, $instance ) {
16
 
17
  $html = '<div>';
18
- $html .= '<!-- noptimize -->';
19
-
20
  $html .= ecwid_get_scriptjs_code();
21
  $html .= ecwid_get_product_browser_url_script();
22
- $html .= '<script data-cfasync="false" type="text/javascript"> xVCategories("style="); </script>';
23
-
24
- $html .= '<!-- /noptimize -->';
25
  $html .= '</div>';
26
 
27
  return $html;
15
  function _render_widget_content( $args, $instance ) {
16
 
17
  $html = '<div>';
 
 
18
  $html .= ecwid_get_scriptjs_code();
19
  $html .= ecwid_get_product_browser_url_script();
20
+ $html .= '<!--noptimize--><script data-cfasync="false" type="text/javascript"> xVCategories("style="); </script><!--/noptimize-->';
 
 
21
  $html .= '</div>';
22
 
23
  return $html;
includes/widgets/nsf-minicart.tpl.php CHANGED
@@ -1,4 +1,3 @@
1
- <!-- noptimize -->
2
  <?php
3
 
4
  echo ecwid_get_scriptjs_code(); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
@@ -12,9 +11,10 @@ echo ecwid_get_product_browser_url_script(); //phpcs:ignore WordPress.Security.E
12
  data-icon='<?php echo esc_attr( $instance[ self::FIELD_ICON ] ); ?>'
13
  ></div>
14
 
 
15
  <script>
16
  if (typeof Ecwid != 'undefined') {
17
  Ecwid.init();
18
  }
19
  </script>
20
- <!-- /noptimize -->
 
1
  <?php
2
 
3
  echo ecwid_get_scriptjs_code(); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
11
  data-icon='<?php echo esc_attr( $instance[ self::FIELD_ICON ] ); ?>'
12
  ></div>
13
 
14
+ <!--noptimize-->
15
  <script>
16
  if (typeof Ecwid != 'undefined') {
17
  Ecwid.init();
18
  }
19
  </script>
20
+ <!--/noptimize-->
js/cache-control.js DELETED
@@ -1,23 +0,0 @@
1
-
2
- ecwidCheckApiCache = function(){
3
- jQuery.getJSON(
4
- ecwidCacheControlParams.ajax_url,
5
- {
6
- action: 'check_api_cache',
7
- }
8
- );
9
- }
10
-
11
- jQuery(document).ready(function() {
12
-
13
- if( document.cookie.search("ecwid_event_is_working_beforeunload") < 0 ) {
14
- ecwidCheckApiCache();
15
- }
16
-
17
- });
18
-
19
- jQuery(window).on('beforeunload', function() {
20
- ecwidCheckApiCache();
21
-
22
- document.cookie = "ecwid_event_is_working_beforeunload=true";
23
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/defer-actions.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var ecwidCheckApiCache = function () {
2
+ if (typeof ecwidCacheControlParams == 'undefined') return;
3
+
4
+ jQuery.getJSON(
5
+ ecwidCacheControlParams.ajax_url,
6
+ {
7
+ action: 'ec_check_api_cache',
8
+ }
9
+ );
10
+ }
11
+
12
+ jQuery(document).ready(function () {
13
+ if (document.cookie.search("ecwid_event_is_working_beforeunload") < 0) {
14
+ ecwidCheckApiCache();
15
+ }
16
+ });
17
+
18
+ jQuery(window).on('beforeunload', function () {
19
+ ecwidCheckApiCache();
20
+ document.cookie = "ecwid_event_is_working_beforeunload=true";
21
+ });
js/frontend.js CHANGED
@@ -41,15 +41,21 @@ jQuery(document).ready(function () {
41
  };
42
 
43
  ecwidShoppingCartMakeStoreLinksUseApiCall(jQuery("a[data-ecwid-page]"));
 
 
44
 
 
45
  if (typeof Ecwid != 'undefined') {
46
  Ecwid.OnAPILoaded.add(function () {
47
-
48
- var font = window.ec.config.chameleonDefaults
49
- && window.ec.config.chameleonDefaults.font
50
- && window.ec.config.chameleonDefaults.font['font-family'] || '';
51
- document.cookie = "ec_store_chameleon_font=" + font;
52
- })
53
- };
54
-
55
- });
 
 
 
41
  };
42
 
43
  ecwidShoppingCartMakeStoreLinksUseApiCall(jQuery("a[data-ecwid-page]"));
44
+ ecwidSaveDynamicCss();
45
+ });
46
 
47
+ var ecwidSaveDynamicCss = function () {
48
  if (typeof Ecwid != 'undefined') {
49
  Ecwid.OnAPILoaded.add(function () {
50
+ if (typeof window.ec.cssLinkElement !== 'undefined') {
51
+ document.cookie = "ec_store_dynamic_css=" + window.ec.cssLinkElement.href;
52
+ }
53
+ });
54
+ }
55
+ }
56
+
57
+ document.addEventListener('setupAfterEcwidLoaded', (e) => {
58
+ Ecwid.OnAPILoaded.add(function () {
59
+ ecwidSaveDynamicCss();
60
+ });
61
+ });
js/static-page.js CHANGED
@@ -6,7 +6,7 @@
6
  var ecwidPageOpened = false;
7
  var autoSwitchStaticToDynamicWhenReady = false;
8
  var autoSwitchStaticToDynamicWhenReadyDefault = false;
9
- var invisibleDynamicContainerStyle = "display: block !important; height: 0 !important; max-height: 0 !important; min-height: 0 !important; overflow-y: auto !important;";
10
  var mainCategoryId = 0;
11
  var initialCategoryOffset = 0;
12
 
@@ -23,19 +23,35 @@
23
  return !staticHtml || !isVisible(staticHtml);
24
  }
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  function processStaticHomePage() {
27
 
28
  window.ec = window.ec || {};
29
  window.ec.storefront = window.ec.storefront || {};
30
  window.ec.storefront.staticPages = window.ec.storefront.staticPages || {};
31
 
32
-
33
  window.ec.storefront.staticPages.switchStaticToDynamic = switchToDynamicMode;
34
 
35
- function isRootCategory() {
36
- return window.location.hash === '' || window.location.hash.indexOf("#!/c/0/") !== -1;
37
- }
38
-
39
  function onDocumentReady(fn) {
40
  if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") {
41
  fn();
@@ -66,6 +82,80 @@
66
  return;
67
  }
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  var mainCategoryIdFromConfig = ec.storefront.staticPages.mainCategoryId;
70
  if (mainCategoryIdFromConfig) {
71
  mainCategoryId = mainCategoryIdFromConfig;
@@ -88,10 +178,6 @@
88
 
89
  window.ec.config = window.ec.config || {};
90
  window.ec.config.navigation_scrolling = "DISABLED";
91
- if (!!('ontouchstart' in window)) {
92
- isTouchDevice = true;
93
- document.body.classList.add('touchable');
94
- }
95
 
96
  if (!isRootCategory()) {
97
  hideStorefront();
@@ -103,14 +189,30 @@
103
 
104
  function setupAfterEcwidLoaded() {
105
 
106
- // если магазин не закрыт для клиента, то в storeClosed не будет true
107
- // если магазин не закрыт для клиента и мы загрузили закрытую плашку проверим это в динамике
 
 
 
 
 
 
 
 
 
108
  Ecwid.OnAPILoaded.add(function () {
 
 
 
 
109
  var storeClosed = window.ecwid_initial_data.data.storeClosed;
110
  var storeClosedWrapper = document.querySelectorAll('.ecwid-maintenance-wrapper');
111
  var storeNotClosedAndWrapperExists = !storeClosed && storeClosedWrapper.length > 0;
112
 
113
- if (!isDynamicMode() && (storeClosed || storeNotClosedAndWrapperExists)) {
 
 
 
114
  switchToDynamicMode();
115
  }
116
  });
@@ -120,12 +222,13 @@
120
  // if we've already switched to dynamic, we don't need to dispatch this event anymore
121
  return;
122
  }
123
-
124
  if (openedPage.type === "CART"
125
  || openedPage.type === "ORDERS"
126
  || openedPage.type === "FAVORITES"
127
  || openedPage.type === "SIGN_IN"
128
- || openedPage.type === "RESET_PASSWORD") {
 
 
129
  // static links from bottom of the page should be processed before page load event finishes,
130
  // so self pre-opening scroll didn't make the page jump
131
  switchToDynamicMode();
@@ -197,18 +300,30 @@
197
  }
198
 
199
  function ecwidLoaded() {
200
- return typeof Ecwid != 'undefined' && !!Ecwid && !!Ecwid.OnAPILoaded && !!Ecwid.OnAPILoaded.add;
201
  }
202
 
203
- if (ecwidLoaded()) {
204
- setupAfterEcwidLoaded();
205
- } else {
206
- var setupIntervalId = setInterval(function () {
207
- if (ecwidLoaded()) {
208
- setupAfterEcwidLoaded();
209
- clearInterval(setupIntervalId);
210
- }
211
- }, 100);
 
 
 
 
 
 
 
 
 
 
 
 
212
  }
213
  });
214
  }
@@ -224,13 +339,13 @@
224
  addClickHandlers('#' + staticId + ' .ec-breadcrumbs a', function (element) {
225
  var categoryId = element.getAttribute('categoryId');
226
  if (categoryId !== mainCategoryId) {
227
- addStaticClickEvent(element, openEcwidPage('category', {'id': categoryId}));
228
  }
229
  });
230
 
231
  var orderByOptions = document.querySelector('#' + staticId + ' .grid__sort select');
232
  if (!!orderByOptions) {
233
- orderByOptions.addEventListener("change", function (event) {
234
  openEcwidPage('category', {
235
  'id': mainCategoryId,
236
  'sort': orderByOptions.value
@@ -252,27 +367,32 @@
252
 
253
  addClickHandlers('#' + staticId + ' .grid-category__card a', function (element) {
254
  var categoryId = element.getAttribute('data-category-id');
255
- addStaticClickEvent(element, openEcwidPage('category', {'id': categoryId}));
256
  });
257
 
258
- addClickHandlers('#' + staticId + ' .grid-product:not(.grid-product--view-all) a', function (element) {
259
  var productId = element.getAttribute('data-product-id');
260
- addStaticClickEvent(element, openEcwidPage('product', {'id': productId}));
261
  });
262
 
263
  addClickHandlers('#' + staticId + ' .grid-product:not(.grid-product--view-all) .grid-product__wrap[data-product-id]', function (element) {
264
  var productId = element.getAttribute('data-product-id');
265
- addStaticClickEvent(element, openEcwidPage('product', {'id': productId}));
266
  });
267
 
268
- addClickHandlers('#' + staticId + ' .grid-product--view-all a' , function (element) {
269
  var categoryId = element.getAttribute('data-category-id');
270
- addStaticClickEvent(element, openEcwidPage('category', {'id': categoryId}));
271
  })
272
 
273
  addClickHandlers('#' + staticId + ' .grid-product__buy-now', function (element) {
274
  var productId = element.getAttribute('data-product-id');
275
- addStaticClickEvent(element, openEcwidPage('product', {'id': productId}));
 
 
 
 
 
276
  });
277
 
278
  addClickHandlers('#' + staticId + ' .footer__link--all-products', function (element) {
@@ -291,11 +411,14 @@
291
  addStaticClickEvent(element, openEcwidPage('cart'));
292
  });
293
 
294
-
295
  addClickHandlers('#' + staticId + ' .footer__link--sigin-in', function (element) {
296
  addStaticClickEvent(element, openEcwidPage('signin'));
297
  });
298
 
 
 
 
 
299
  addClickHandlers('#' + staticId + ' .pager__button', function (element) {
300
  var pageNumber = element.getAttribute('data-page-number') || 2;
301
  addStaticClickEvent(element, openEcwidPage('category', {
@@ -312,6 +435,11 @@
312
  }));
313
  });
314
 
 
 
 
 
 
315
  }
316
 
317
  function addStaticClickEvent(el, callback) {
@@ -328,11 +456,11 @@
328
  y = e.touches[0].clientY;
329
  dx = 0;
330
  dy = 0;
331
- });
332
  el.addEventListener('touchmove', function (e) {
333
  dx = e.changedTouches[0].clientX - x;
334
  dy = e.changedTouches[0].clientY - y;
335
- });
336
  el.addEventListener('touchend', function (e) {
337
  if (isTap && Math.abs(dx) < 10 && Math.abs(dy) < 10) {
338
  callback(e);
@@ -351,10 +479,17 @@
351
 
352
  function openEcwidPage(page, params) {
353
  return function (e) {
 
 
 
 
 
 
 
354
  e.preventDefault();
355
  // we must wait for Ecwid first page to be ready before changing it
356
  addOnPageLoadedCallback(function () {
357
- if (isDynamicMode()) {
358
  // if we've already switched to dynamic, we don't need to dispatch this event anymore
359
  return;
360
  }
@@ -365,7 +500,7 @@
365
  ecwidPageOpened = true;
366
  var element = find('#' + staticId + " .ec-wrapper");
367
  if (!!element) {
368
- elementsClassListAction([element], function(list) {
369
  list.add("ec-wrapper--transition");
370
  });
371
  }
@@ -374,13 +509,12 @@
374
  }
375
  }
376
 
377
- function addOnPageLoadedCallback(callback, attempt) {
378
- // Иногда при загрузке витрины (статической версии) на странице еще не определен Ecwid.OnPageLoaded.
379
- // Надо подождать пока он появится, отложенно отработать клик пользователя (например открыть детали товара).
380
- // Время ретраев - 2 секунды. 50 ms * 40 попыток = 2000 ms.
381
- // Время выбрано по времени загрузки script.js https://graphweb.ecwid.com:3000/d/000000007/ecwid-performance-metrics
382
- // 99 перцентиль иногда поднимается до 1.5 секунд. Сделал небольшой запас
383
 
 
 
384
  if (attempt >= 40) {
385
  if (!!console) {
386
  console.warn("failed to add Ecwid.OnPageLoaded callback");
@@ -388,7 +522,7 @@
388
  return;
389
  }
390
 
391
- if (typeof(Ecwid) == 'object' && typeof(Ecwid.OnPageLoaded) == 'object') {
392
  Ecwid.OnPageLoaded.add(callback);
393
  } else {
394
  setTimeout(function () {
@@ -411,6 +545,8 @@
411
  dynamicEl.style.maxHeight = "";
412
  dynamicEl.style.minHeight = "";
413
  dynamicEl.style.overflowY = "";
 
 
414
  dynamicEl.style.display = "block";
415
  }
416
 
@@ -443,7 +579,7 @@
443
 
444
  var element = find('#' + staticId + " .ec-wrapper");
445
  if (!!element) {
446
- elementsClassListAction([element], function(list) {
447
  list.remove("ec-wrapper--transition");
448
  });
449
  }
@@ -459,7 +595,7 @@
459
  }
460
  var wrapers = document.querySelectorAll('.ec-wrapper--animated-transitions');
461
  var arrWrapers = Array.prototype.slice.call(wrapers);
462
- elementsClassListAction(arrWrapers, function(list) {
463
  list.remove('ec-wrapper--animated-transitions');
464
  });
465
  }
@@ -470,7 +606,7 @@
470
  }
471
  for (var key in elements) {
472
  var list = elements[key].classList;
473
- if (typeof list != "undefined") {
474
  callback(list);
475
  }
476
  }
@@ -478,4 +614,49 @@
478
 
479
  processStaticHomePage();
480
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
481
  })();
6
  var ecwidPageOpened = false;
7
  var autoSwitchStaticToDynamicWhenReady = false;
8
  var autoSwitchStaticToDynamicWhenReadyDefault = false;
9
+ var invisibleDynamicContainerStyle = "display: block !important; height: 0 !important; max-height: 0 !important; min-height: 0 !important; overflow-y: auto !important; margin: 0 !important; padding: 0 !important;";
10
  var mainCategoryId = 0;
11
  var initialCategoryOffset = 0;
12
 
23
  return !staticHtml || !isVisible(staticHtml);
24
  }
25
 
26
+ function isRootCategory() {
27
+ var urlHash = window.location.hash;
28
+ return urlHash === '' || (urlHash.indexOf("#!/c/0/") === -1 && urlHash.indexOf("#!//c/0/") === -1);
29
+ }
30
+
31
+ function loadScriptJs(onScriptJsLoadedCallback) {
32
+ var scriptJs = document.createElement('script');
33
+ scriptJs.src = ec.storefront.staticPages.lazyLoading.scriptJsLink;
34
+ if (scriptJs.readyState) {
35
+ scriptJs.onreadystatechange = function () {
36
+ if (scriptJs.readyState === 'loaded' || scriptJs.readyState === 'complete') {
37
+ onScriptJsLoadedCallback();
38
+ }
39
+ };
40
+ } else {
41
+ scriptJs.onload = onScriptJsLoadedCallback;
42
+ }
43
+ var dynamicEl = find("#" + ec.storefront.staticPages.dynamicContainerID);
44
+ dynamicEl.appendChild(scriptJs);
45
+ };
46
+
47
  function processStaticHomePage() {
48
 
49
  window.ec = window.ec || {};
50
  window.ec.storefront = window.ec.storefront || {};
51
  window.ec.storefront.staticPages = window.ec.storefront.staticPages || {};
52
 
 
53
  window.ec.storefront.staticPages.switchStaticToDynamic = switchToDynamicMode;
54
 
 
 
 
 
55
  function onDocumentReady(fn) {
56
  if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") {
57
  fn();
82
  return;
83
  }
84
 
85
+ if (window.location.hash.indexOf("#!/c/0") !== -1) {
86
+ var element = document.querySelector("#" + staticId);
87
+ element.scrollIntoView(true);
88
+ }
89
+
90
+ if (!!('ontouchstart' in window)) {
91
+ isTouchDevice = true;
92
+ document.body.classList.add('touchable');
93
+ }
94
+
95
+ if (typeof ec.storefront.staticPages.lazyLoading !== "undefined") {
96
+ if (typeof ec.storefront.staticPages.lazyLoading.scriptJsLink === "undefined") {
97
+ if (!!console) {
98
+ console.warn("Storefront lazy loading is enabled, but no scriptJsLink is provided");
99
+ }
100
+ return;
101
+ }
102
+ if (typeof ec.storefront.staticPages.lazyLoading.xProductBrowserArguments === "undefined") {
103
+ if (!!console) {
104
+ console.warn("Storefront lazy loading is enabled, but no xProductBrowser arguments are provided");
105
+ }
106
+ return;
107
+ }
108
+
109
+ toggleLazyLoadingEvents(true);
110
+
111
+ var lazyLoading = true;
112
+
113
+ function lazyLoadingEventHandler() {
114
+ if (typeof lazyLoading === 'undefined') {
115
+ if (!!console) {
116
+ console.warn("Unable to fetch script.js outside of lazy loading mode");
117
+ }
118
+ } else {
119
+ toggleLazyLoadingEvents(false);
120
+ loadScriptJs(lazyInitDynamic);
121
+ }
122
+ }
123
+
124
+ var lazyInitDynamic = function () {
125
+ xProductBrowser.apply(this, ec.storefront.staticPages.lazyLoading.xProductBrowserArguments);
126
+
127
+ setupEcwidWhenLoaded();
128
+ }
129
+
130
+ function toggleLazyLoadingEvents(add) {
131
+ var staticDivEventsForLazyLoading = ['mousedown', 'mouseup', 'mousemove', 'contextmenu', 'keydown', 'keyup'];
132
+ var staticDivTouchEventsForLazyLoading = ['touchstart', 'touchend', 'touchcancel', 'touchmove'];
133
+
134
+ var toggleEvent = function (el, add, event) {
135
+ if (add) {
136
+ el.addEventListener(event, lazyLoadingEventHandler, { passive: true });
137
+ } else {
138
+ el.removeEventListener(event, lazyLoadingEventHandler);
139
+ }
140
+ }
141
+
142
+ //var staticEl = find('#' + staticId);
143
+ if (isTouchDevice) {
144
+ staticDivTouchEventsForLazyLoading.forEach(
145
+ function applyEvent(event) {
146
+ toggleEvent(document, add, event);
147
+ }
148
+ );
149
+ } else {
150
+ staticDivEventsForLazyLoading.forEach(
151
+ function applyEvent(event) {
152
+ toggleEvent(document, add, event);
153
+ }
154
+ );
155
+ }
156
+ }
157
+ }
158
+
159
  var mainCategoryIdFromConfig = ec.storefront.staticPages.mainCategoryId;
160
  if (mainCategoryIdFromConfig) {
161
  mainCategoryId = mainCategoryIdFromConfig;
178
 
179
  window.ec.config = window.ec.config || {};
180
  window.ec.config.navigation_scrolling = "DISABLED";
 
 
 
 
181
 
182
  if (!isRootCategory()) {
183
  hideStorefront();
189
 
190
  function setupAfterEcwidLoaded() {
191
 
192
+ const event = document.createEvent('Event');
193
+ event.initEvent('setupAfterEcwidLoaded', true, false);
194
+ document.dispatchEvent(event);
195
+
196
+ var cartWidgets = document.getElementsByClassName('ec-cart-widget');
197
+ if (cartWidgets.length > 0) {
198
+ Ecwid.init();
199
+ }
200
+
201
+ // if a store is opened for a client, then the storeClosed won't be true
202
+ // if a store is opened for a client and we've uploaded a closed banner, then we check it in dynamic
203
  Ecwid.OnAPILoaded.add(function () {
204
+ if (isDynamicMode()) {
205
+ // if we've already switched to dynamic, we don't need to dispatch this event anymore
206
+ return;
207
+ }
208
  var storeClosed = window.ecwid_initial_data.data.storeClosed;
209
  var storeClosedWrapper = document.querySelectorAll('.ecwid-maintenance-wrapper');
210
  var storeNotClosedAndWrapperExists = !storeClosed && storeClosedWrapper.length > 0;
211
 
212
+ if (storeClosed
213
+ || storeNotClosedAndWrapperExists
214
+ || hasEcwidMessages()
215
+ ) {
216
  switchToDynamicMode();
217
  }
218
  });
222
  // if we've already switched to dynamic, we don't need to dispatch this event anymore
223
  return;
224
  }
 
225
  if (openedPage.type === "CART"
226
  || openedPage.type === "ORDERS"
227
  || openedPage.type === "FAVORITES"
228
  || openedPage.type === "SIGN_IN"
229
+ || openedPage.type === "RESET_PASSWORD"
230
+ || hasEcwidMessages()
231
+ ) {
232
  // static links from bottom of the page should be processed before page load event finishes,
233
  // so self pre-opening scroll didn't make the page jump
234
  switchToDynamicMode();
300
  }
301
 
302
  function ecwidLoaded() {
303
+ return !!Ecwid && !!Ecwid.OnAPILoaded && !!Ecwid.OnAPILoaded.add;
304
  }
305
 
306
+ function hasEcwidMessages() {
307
+ // If the merchant has at least one custom label, then switch to dynamics regardless of the page type or click
308
+ return !!window.ecwidMessages && Object.keys(window.ecwidMessages).length > 0;
309
+ }
310
+
311
+ var setupEcwidWhenLoaded = function () {
312
+ if (ecwidLoaded()) {
313
+ setupAfterEcwidLoaded();
314
+ } else {
315
+ var setupIntervalId = setInterval(function () {
316
+ if (ecwidLoaded()) {
317
+ setupAfterEcwidLoaded();
318
+ clearInterval(setupIntervalId);
319
+ }
320
+ }, 100);
321
+ }
322
+ };
323
+
324
+ if (typeof lazyLoading === 'undefined') {
325
+ // Follow legacy dynamic store initialization flow
326
+ setupEcwidWhenLoaded();
327
  }
328
  });
329
  }
339
  addClickHandlers('#' + staticId + ' .ec-breadcrumbs a', function (element) {
340
  var categoryId = element.getAttribute('categoryId');
341
  if (categoryId !== mainCategoryId) {
342
+ addStaticClickEvent(element, openEcwidPage('category', { 'id': categoryId }));
343
  }
344
  });
345
 
346
  var orderByOptions = document.querySelector('#' + staticId + ' .grid__sort select');
347
  if (!!orderByOptions) {
348
+ orderByOptions.addEventListener('change', function (event) {
349
  openEcwidPage('category', {
350
  'id': mainCategoryId,
351
  'sort': orderByOptions.value
367
 
368
  addClickHandlers('#' + staticId + ' .grid-category__card a', function (element) {
369
  var categoryId = element.getAttribute('data-category-id');
370
+ addStaticClickEvent(element, openEcwidPage('category', { 'id': categoryId }));
371
  });
372
 
373
+ addClickHandlers('#' + staticId + ' .grid-product:not(.grid-product--view-all) a:not(.open-external-url)', function (element) {
374
  var productId = element.getAttribute('data-product-id');
375
+ addStaticClickEvent(element, openEcwidPage('product', { 'id': productId }));
376
  });
377
 
378
  addClickHandlers('#' + staticId + ' .grid-product:not(.grid-product--view-all) .grid-product__wrap[data-product-id]', function (element) {
379
  var productId = element.getAttribute('data-product-id');
380
+ addStaticClickEvent(element, openEcwidPage('product', { 'id': productId }));
381
  });
382
 
383
+ addClickHandlers('#' + staticId + ' .grid-product--view-all a', function (element) {
384
  var categoryId = element.getAttribute('data-category-id');
385
+ addStaticClickEvent(element, openEcwidPage('category', { 'id': categoryId }));
386
  })
387
 
388
  addClickHandlers('#' + staticId + ' .grid-product__buy-now', function (element) {
389
  var productId = element.getAttribute('data-product-id');
390
+ addStaticClickEvent(element, openEcwidPage('product', { 'id': productId }));
391
+ });
392
+
393
+ addClickHandlers('#' + staticId + ' .footer__link--gift-card', function (element) {
394
+ var productId = element.getAttribute('data-product-id');
395
+ addStaticClickEvent(element, openEcwidPage('product', { 'id': productId }));
396
  });
397
 
398
  addClickHandlers('#' + staticId + ' .footer__link--all-products', function (element) {
411
  addStaticClickEvent(element, openEcwidPage('cart'));
412
  });
413
 
 
414
  addClickHandlers('#' + staticId + ' .footer__link--sigin-in', function (element) {
415
  addStaticClickEvent(element, openEcwidPage('signin'));
416
  });
417
 
418
+ addClickHandlers('#' + staticId + ' .footer__link--my-account', function (element) {
419
+ addStaticClickEvent(element, openEcwidPage('account/settings'));
420
+ });
421
+
422
  addClickHandlers('#' + staticId + ' .pager__button', function (element) {
423
  var pageNumber = element.getAttribute('data-page-number') || 2;
424
  addStaticClickEvent(element, openEcwidPage('category', {
435
  }));
436
  });
437
 
438
+ addClickHandlers('#' + staticId + ' .open-external-url', function (element) {
439
+ addStaticClickEvent(element, function (e) {
440
+ e.stopPropagation();
441
+ });
442
+ });
443
  }
444
 
445
  function addStaticClickEvent(el, callback) {
456
  y = e.touches[0].clientY;
457
  dx = 0;
458
  dy = 0;
459
+ }, { passive: true });
460
  el.addEventListener('touchmove', function (e) {
461
  dx = e.changedTouches[0].clientX - x;
462
  dy = e.changedTouches[0].clientY - y;
463
+ }, { passive: true });
464
  el.addEventListener('touchend', function (e) {
465
  if (isTap && Math.abs(dx) < 10 && Math.abs(dy) < 10) {
466
  callback(e);
479
 
480
  function openEcwidPage(page, params) {
481
  return function (e) {
482
+ if (isCtrlClickOnProductEvent(page, e)) {
483
+ // In case product element in grid was clicked with ctrl/meta key, do not invoke e.preventDefault()
484
+ // and do nothing. Event will be handled and processed by default ctrl/meta + click handler on
485
+ // underlying <a> element. New background tab with product page will be opened.
486
+ return;
487
+ }
488
+
489
  e.preventDefault();
490
  // we must wait for Ecwid first page to be ready before changing it
491
  addOnPageLoadedCallback(function () {
492
+ if (isDynamicMode() && ecwidPageOpened) {
493
  // if we've already switched to dynamic, we don't need to dispatch this event anymore
494
  return;
495
  }
500
  ecwidPageOpened = true;
501
  var element = find('#' + staticId + " .ec-wrapper");
502
  if (!!element) {
503
+ elementsClassListAction([element], function (list) {
504
  list.add("ec-wrapper--transition");
505
  });
506
  }
509
  }
510
  }
511
 
512
+ function isCtrlClickOnProductEvent(page, event) {
513
+ return page === 'product' && (event.ctrlKey || event.metaKey)
514
+ }
 
 
 
515
 
516
+ function addOnPageLoadedCallback(callback, attempt) {
517
+ // let's wait for the Ecwid environment to be loaded for up to 2000 milliseconds
518
  if (attempt >= 40) {
519
  if (!!console) {
520
  console.warn("failed to add Ecwid.OnPageLoaded callback");
522
  return;
523
  }
524
 
525
+ if (typeof (Ecwid) == 'object' && typeof (Ecwid.OnPageLoaded) == 'object') {
526
  Ecwid.OnPageLoaded.add(callback);
527
  } else {
528
  setTimeout(function () {
545
  dynamicEl.style.maxHeight = "";
546
  dynamicEl.style.minHeight = "";
547
  dynamicEl.style.overflowY = "";
548
+ dynamicEl.style.margin = "";
549
+ dynamicEl.style.padding = "";
550
  dynamicEl.style.display = "block";
551
  }
552
 
579
 
580
  var element = find('#' + staticId + " .ec-wrapper");
581
  if (!!element) {
582
+ elementsClassListAction([element], function (list) {
583
  list.remove("ec-wrapper--transition");
584
  });
585
  }
595
  }
596
  var wrapers = document.querySelectorAll('.ec-wrapper--animated-transitions');
597
  var arrWrapers = Array.prototype.slice.call(wrapers);
598
+ elementsClassListAction(arrWrapers, function (list) {
599
  list.remove('ec-wrapper--animated-transitions');
600
  });
601
  }
606
  }
607
  for (var key in elements) {
608
  var list = elements[key].classList;
609
+ if (typeof list != 'undefined') {
610
  callback(list);
611
  }
612
  }
614
 
615
  processStaticHomePage();
616
 
617
+ function forceDynamicLoadingIfRequired() {
618
+ if (typeof ec.storefront.staticPages.lazyLoading === "undefined") {
619
+ if (!!console) {
620
+ console.warn("Storefront lazy loading is not enabled to switch in dynamic mode");
621
+ }
622
+ return;
623
+ }
624
+ if (typeof ec.storefront.staticPages.lazyLoading.scriptJsLink === "undefined") {
625
+ if (!!console) {
626
+ console.warn("No scriptJsLink is provided to switch in dynamic mode");
627
+ }
628
+ return;
629
+ }
630
+ if (typeof ec.storefront.staticPages.lazyLoading.xProductBrowserArguments === "undefined") {
631
+ if (!!console) {
632
+ console.warn("No xProductBrowser arguments are provided to switch in dynamic mode");
633
+ }
634
+ return;
635
+ }
636
+
637
+ var staticContainer = document.getElementById(ec.storefront.staticPages.staticContainerID);
638
+
639
+ var rootCategory = isRootCategory();
640
+ if (!rootCategory) {
641
+ while (staticContainer.lastChild) {
642
+ staticContainer.lastChild.remove();
643
+ }
644
+
645
+ var onScriptJsLoadedCallback = function () {
646
+ xProductBrowser.apply(this, ec.storefront.staticPages.lazyLoading.xProductBrowserArguments);
647
+ }
648
+
649
+ loadScriptJs(onScriptJsLoadedCallback);
650
+ } else {
651
+ staticContainer.style.height = "";
652
+ staticContainer.style.maxHeight = "";
653
+ staticContainer.style.minHeight = "";
654
+ staticContainer.style.overflowY = "";
655
+ }
656
+ }
657
+
658
+ window.ec = window.ec || {};
659
+ window.ec.storefront = window.ec.storefront || {};
660
+ window.ec.storefront.staticPages = window.ec.storefront.staticPages || {};
661
+ window.ec.storefront.staticPages.forceDynamicLoadingIfRequired = forceDynamicLoadingIfRequired;
662
  })();
lib/ecwid_platform.php CHANGED
@@ -23,7 +23,7 @@ class EcwidPlatform {
23
  const TRANSIENTS_LIMIT = 5000;
24
 
25
  public static function get_store_id() {
26
- return get_ecwid_store_id();
27
  }
28
 
29
  public static function init_crypt( $force = false ) {
@@ -153,7 +153,8 @@ class EcwidPlatform {
153
  public static function cache_log_record( $operation, $params ) {
154
 
155
  if ( ! get_option( self::OPTION_LOG_CACHE, false ) ) {
156
- return; }
 
157
 
158
  if ( ! $params ) {
159
  $params = array();
@@ -233,7 +234,7 @@ class EcwidPlatform {
233
  }
234
 
235
  public static function report_error( $error ) {
236
- ecwid_log_error( json_encode( $error ) );
237
  }
238
 
239
  public static function fetch_url( $url, $options = array() ) {
@@ -463,7 +464,7 @@ class EcwidPlatform {
463
  }
464
 
465
  public static function get_from_catalog_cache( $key ) {
466
- $cache_name = self::_build_cache_name( $key, 'catalog' );
467
 
468
  $result = self::cache_get( $cache_name );
469
 
@@ -483,8 +484,10 @@ class EcwidPlatform {
483
  )
484
  );
485
 
486
- if ( $result && self::get( self::CATALOG_CACHE_VALID_FROM ) > $valid_from ) {
487
  return $result['data'];
 
 
488
  }
489
 
490
  return false;
@@ -533,7 +536,7 @@ class EcwidPlatform {
533
  }
534
 
535
  public static function invalidate_products_cache_from( $time = null ) {
536
- self::_invalidate_cache_from( self::PRODUCTS_CACHE_VALID_FROM, $time );
537
  }
538
 
539
  public static function invalidate_categories_cache_from( $time = null ) {
@@ -556,7 +559,7 @@ class EcwidPlatform {
556
  public static function is_need_clear_transients() {
557
  global $wpdb;
558
 
559
- $count_transients = $wpdb->get_var(
560
  "
561
  SELECT COUNT(*)
562
  FROM {$wpdb->options}
@@ -574,7 +577,7 @@ class EcwidPlatform {
574
  public static function clear_all_transients() {
575
  global $wpdb;
576
 
577
- $wpdb->query(
578
  "
579
  DELETE
580
  FROM {$wpdb->options}
23
  const TRANSIENTS_LIMIT = 5000;
24
 
25
  public static function get_store_id() {
26
+ return get_ecwid_store_id();
27
  }
28
 
29
  public static function init_crypt( $force = false ) {
153
  public static function cache_log_record( $operation, $params ) {
154
 
155
  if ( ! get_option( self::OPTION_LOG_CACHE, false ) ) {
156
+ return;
157
+ }
158
 
159
  if ( ! $params ) {
160
  $params = array();
234
  }
235
 
236
  public static function report_error( $error ) {
237
+ ecwid_log_error( wp_json_encode( $error ) );
238
  }
239
 
240
  public static function fetch_url( $url, $options = array() ) {
464
  }
465
 
466
  public static function get_from_catalog_cache( $key ) {
467
+ $cache_name = self::_build_cache_name( $key, 'catalog' );
468
 
469
  $result = self::cache_get( $cache_name );
470
 
484
  )
485
  );
486
 
487
+ if ( $result && isset( $result['data']->lastUpdated ) && $result['data']->lastUpdated > $valid_from ) {
488
  return $result['data'];
489
+ } else {
490
+ self::cache_reset( $cache_name );
491
  }
492
 
493
  return false;
536
  }
537
 
538
  public static function invalidate_products_cache_from( $time = null ) {
539
+ self::_invalidate_cache_from( self::PRODUCTS_CACHE_VALID_FROM, $time );
540
  }
541
 
542
  public static function invalidate_categories_cache_from( $time = null ) {
559
  public static function is_need_clear_transients() {
560
  global $wpdb;
561
 
562
+ $count_transients = $wpdb->get_var( //phpcs:ignore WordPress.DB.DirectDatabaseQuery
563
  "
564
  SELECT COUNT(*)
565
  FROM {$wpdb->options}
577
  public static function clear_all_transients() {
578
  global $wpdb;
579
 
580
+ $wpdb->query( //phpcs:ignore WordPress.DB.DirectDatabaseQuery
581
  "
582
  DELETE
583
  FROM {$wpdb->options}
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: Ecwid
3
  Tags: ecommerce, e-commerce, storefront, shopping cart, online store
4
  Requires at least: 4.4
5
  Tested up to: 6.1
6
- Stable tag: 6.10.29
7
 
8
  Powerful, easy to use ecommerce shopping cart for WordPress. Sell on Facebook and Instagram. iPhone & Android apps. Superb support. Free plan available.
9
 
@@ -152,6 +152,9 @@ You can use Ecwid’s built-in import tools to copy your store products from any
152
 
153
  == Changelog ==
154
 
 
 
 
155
  = 6.10.29 - Nov 07, 2022 =
156
  - **WordPress 6.1 and Twenty Twenty Three theme compatibility.** The new WordPress version with the 2023 theme is released. The Ecwid ecommerce shopping cart plugin is ready for the new release — everything works well in your WordPress admin and storefront pages. Feel free to upgrade your site to WordPress 6.1 and try a new theme.
157
  - Compatibility improvements with XML Sitemaps plugin. If you are using the XML Sitemaps plugin, you may be experiencing an issue where storefront products links are not being added to sitemap. We've fixed it.
3
  Tags: ecommerce, e-commerce, storefront, shopping cart, online store
4
  Requires at least: 4.4
5
  Tested up to: 6.1
6
+ Stable tag: 6.11
7
 
8
  Powerful, easy to use ecommerce shopping cart for WordPress. Sell on Facebook and Instagram. iPhone & Android apps. Superb support. Free plan available.
9
 
152
 
153
  == Changelog ==
154
 
155
+ = 6.11 - Nov 29, 2022 =
156
+ - **New cool feature — speedup of storefront loading.** We drastically improved the load speed of Ecwid stores published on WordPress. We optimized the resources loaded by the plugin to accelerate the loading of store pages and ecommerce widgets (shopping cart icon, product search, etc). The improvement greatly enhances the user experience and boosts your store SEO. You will now get better performance scores when checking your store pages in Google PageSpeed Insights. In the coming weeks, we will gradually enable this feature for all of our users.
157
+
158
  = 6.10.29 - Nov 07, 2022 =
159
  - **WordPress 6.1 and Twenty Twenty Three theme compatibility.** The new WordPress version with the 2023 theme is released. The Ecwid ecommerce shopping cart plugin is ready for the new release — everything works well in your WordPress admin and storefront pages. Feel free to upgrade your site to WordPress 6.1 and try a new theme.
160
  - Compatibility improvements with XML Sitemaps plugin. If you are using the XML Sitemaps plugin, you may be experiencing an issue where storefront products links are not being added to sitemap. We've fixed it.
templates/shortcode-pb-placeholder.php ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div id="ec-store-pb-placeholder">
2
+ <style>
3
+ /* PB placeholder */
4
+ .ecwid-pb-placeholder {
5
+ box-sizing: border-box;
6
+ opacity: 0;
7
+ min-height: 400px;
8
+ padding-top: 1px;
9
+ }
10
+
11
+ .ecwid-pb-placeholder>div {
12
+ box-sizing: border-box;
13
+ }
14
+
15
+ .ecwid-pb-placeholder--light,
16
+ .ecwid-pb-placeholder--dark {
17
+ opacity: 1;
18
+ }
19
+
20
+ .ecwid-pb-placeholder__grid {
21
+ overflow: hidden;
22
+ width: 100%;
23
+ max-width: 1000px;
24
+ height: 280px;
25
+ margin: 35px auto 50px;
26
+ text-align: center;
27
+ transition: opacity .15s ease-in-out;
28
+ }
29
+
30
+ .ecwid-pb-placeholder__wrap {
31
+ margin-right: -30px;
32
+ margin-left: -30px;
33
+ }
34
+
35
+ .ecwid-pb-placeholder__grid-cell {
36
+ display: inline-block;
37
+ width: 282px;
38
+ height: 280px;
39
+ line-height: 280px;
40
+ white-space: nowrap;
41
+ }
42
+
43
+ .ecwid-pb-placeholder__product {
44
+ width: 222px;
45
+ height: 222px;
46
+ margin: 0 auto;
47
+ padding: 0;
48
+ }
49
+
50
+ .ecwid-pb-placeholder__title {
51
+ max-width: 222px;
52
+ margin: 12px auto;
53
+ padding: 0;
54
+ }
55
+
56
+ .ecwid-pb-placeholder__title>div {
57
+ height: 7px;
58
+ margin: 12px auto;
59
+ padding: 0;
60
+ }
61
+
62
+ .ecwid-pb-placeholder__title>div:nth-child(3) {
63
+ max-width: 100px;
64
+ }
65
+
66
+ /* PB placeholder light */
67
+ .ecwid-pb-placeholder--light .ecwid-pb-placeholder__grid-cell .ecwid-pb-placeholder__product,
68
+ .ecwid-pb-placeholder--light .ecwid-pb-placeholder__grid-cell .ecwid-pb-placeholder__title>div {
69
+ background-color: rgba(0, 0, 0, .03);
70
+ }
71
+
72
+ .ecwid-pb-placeholder--light.ecwid-pb-placeholder--animate .ecwid-pb-placeholder__grid-cell:nth-child(1) .ecwid-pb-placeholder__product {
73
+ animation: pb-flash-light 800ms ease-in-out 0ms infinite;
74
+ }
75
+
76
+ .ecwid-pb-placeholder--light.ecwid-pb-placeholder--animate .ecwid-pb-placeholder__grid-cell:nth-child(1) .ecwid-pb-placeholder__title>div {
77
+ animation: pb-flash-light 800ms ease-in-out 83ms infinite;
78
+ }
79
+
80
+ .ecwid-pb-placeholder--light.ecwid-pb-placeholder--animate .ecwid-pb-placeholder__grid-cell:nth-child(2) .ecwid-pb-placeholder__product {
81
+ animation: pb-flash-light 800ms ease-in-out 167ms infinite;
82
+ }
83
+
84
+ .ecwid-pb-placeholder--light.ecwid-pb-placeholder--animate .ecwid-pb-placeholder__grid-cell:nth-child(2) .ecwid-pb-placeholder__title>div {
85
+ animation: pb-flash-light 800ms ease-in-out 250ms infinite;
86
+ }
87
+
88
+ .ecwid-pb-placeholder--light.ecwid-pb-placeholder--animate .ecwid-pb-placeholder__grid-cell:nth-child(3) .ecwid-pb-placeholder__product {
89
+ animation: pb-flash-light 800ms ease-in-out 333ms infinite;
90
+ }
91
+
92
+ .ecwid-pb-placeholder--light.ecwid-pb-placeholder--animate .ecwid-pb-placeholder__grid-cell:nth-child(3) .ecwid-pb-placeholder__title>div {
93
+ animation: pb-flash-light 800ms ease-in-out 416ms infinite;
94
+ }
95
+
96
+ /* PB placehoder dark */
97
+ .ecwid-pb-placeholder--dark .ecwid-pb-placeholder__grid-cell .ecwid-pb-placeholder__product,
98
+ .ecwid-pb-placeholder--dark .ecwid-pb-placeholder__grid-cell .ecwid-pb-placeholder__title>div {
99
+ background-color: rgba(255, 255, 255, .1);
100
+ }
101
+
102
+ .ecwid-pb-placeholder--dark.ecwid-pb-placeholder--animate .ecwid-pb-placeholder__grid-cell:nth-child(1) .ecwid-pb-placeholder__product {
103
+ animation: pb-flash-dark 800ms ease-in-out 0ms infinite;
104
+ }
105
+
106
+ .ecwid-pb-placeholder--dark.ecwid-pb-placeholder--animate .ecwid-pb-placeholder__grid-cell:nth-child(1) .ecwid-pb-placeholder__title>div {
107
+ animation: pb-flash-dark 800ms ease-in-out 83ms infinite;
108
+ }
109
+
110
+ .ecwid-pb-placeholder--dark.ecwid-pb-placeholder--animate .ecwid-pb-placeholder__grid-cell:nth-child(2) .ecwid-pb-placeholder__product {
111
+ animation: pb-flash-dark 800ms ease-in-out 167ms infinite;
112
+ }
113
+
114
+ .ecwid-pb-placeholder--dark.ecwid-pb-placeholder--animate .ecwid-pb-placeholder__grid-cell:nth-child(2) .ecwid-pb-placeholder__title>div {
115
+ animation: pb-flash-dark 800ms ease-in-out 250ms infinite;
116
+ }
117
+
118
+ .ecwid-pb-placeholder--dark.ecwid-pb-placeholder--animate .ecwid-pb-placeholder__grid-cell:nth-child(3) .ecwid-pb-placeholder__product {
119
+ animation: pb-flash-dark 800ms ease-in-out 333ms infinite;
120
+ }
121
+
122
+ .ecwid-pb-placeholder--dark.ecwid-pb-placeholder--animate .ecwid-pb-placeholder__grid-cell:nth-child(3) .ecwid-pb-placeholder__title>div {
123
+ animation: pb-flash-dark 800ms ease-in-out 416ms infinite;
124
+ }
125
+
126
+ @keyframes pb-flash-light {
127
+ 0% {
128
+ background-color: rgba(0, 0, 0, .03);
129
+ }
130
+
131
+ 30% {
132
+ background-color: rgba(0, 0, 0, .047);
133
+ }
134
+
135
+ 100% {
136
+ background-color: rgba(0, 0, 0, .03);
137
+ }
138
+ }
139
+
140
+ @keyframes pb-flash-dark {
141
+ 0% {
142
+ background-color: rgba(255, 255, 255, .06);
143
+ }
144
+
145
+ 30% {
146
+ background-color: rgba(255, 255, 255, .1);
147
+ }
148
+
149
+ 100% {
150
+ background-color: rgba(255, 255, 255, .06);
151
+ }
152
+ }
153
+ </style>
154
+ <div class="ecwid-pb-placeholder ecwid-pb-placeholder--animate ecwid-pb-placeholder--light" id="ecwidStorefrontPlaceholder">
155
+ <div class="ecwid-pb-placeholder__grid">
156
+ <div class="ecwid-pb-placeholder__wrap">
157
+ <div class="ecwid-pb-placeholder__grid-cell">
158
+ <div class="ecwid-pb-placeholder__product"></div>
159
+ <div class="ecwid-pb-placeholder__title">
160
+ <div></div>
161
+ <div></div>
162
+ <div></div>
163
+ </div>
164
+ </div>
165
+ <div class="ecwid-pb-placeholder__grid-cell">
166
+ <div class="ecwid-pb-placeholder__product"></div>
167
+ <div class="ecwid-pb-placeholder__title">
168
+ <div></div>
169
+ <div></div>
170
+ <div></div>
171
+ </div>
172
+ </div>
173
+ <div class="ecwid-pb-placeholder__grid-cell">
174
+ <div class="ecwid-pb-placeholder__product"></div>
175
+ <div class="ecwid-pb-placeholder__title">
176
+ <div></div>
177
+ <div></div>
178
+ <div></div>
179
+ </div>
180
+ </div>
181
+ </div>
182
+ </div>
183
+ <div class="ecwid-pb-placeholder__grid">
184
+ <div class="ecwid-pb-placeholder__wrap">
185
+ <div class="ecwid-pb-placeholder__grid-cell">
186
+ <div class="ecwid-pb-placeholder__product"></div>
187
+ <div class="ecwid-pb-placeholder__title">
188
+ <div></div>
189
+ <div></div>
190
+ <div></div>
191
+ </div>
192
+ </div>
193
+ <div class="ecwid-pb-placeholder__grid-cell">
194
+ <div class="ecwid-pb-placeholder__product"></div>
195
+ <div class="ecwid-pb-placeholder__title">
196
+ <div></div>
197
+ <div></div>
198
+ <div></div>
199
+ </div>
200
+ </div>
201
+ <div class="ecwid-pb-placeholder__grid-cell">
202
+ <div class="ecwid-pb-placeholder__product"></div>
203
+ <div class="ecwid-pb-placeholder__title">
204
+ <div></div>
205
+ <div></div>
206
+ <div></div>
207
+ </div>
208
+ </div>
209
+ </div>
210
+ </div>
211
+ </div>
212
+ </div>