Ecwid Ecommerce Shopping Cart - Version 4.9

Version Description

  • Integration with Wordpress search. This new feature will make your ecommerce site search find store products among other site pages and posts. So, when your customer searches for something on your site, they will see both site content and store products in the search results and will be able to navigate directly to the product pages from there. Please enable it on the Ecwid/Advanced settings page in your Wordpress backend and do not forget to click "Synchronize products" link. The feature is now in beta stage and we are actively improving it. So if you face any trouble with it, please let us know.
Download this release

Release Info

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

Code changes from version 4.8 to 4.9

css/settings.css CHANGED
@@ -765,4 +765,97 @@ label.premium-feature svg path {
765
  top: 46px;
766
  bottom: 0px;
767
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
768
  }
765
  top: 46px;
766
  bottom: 0px;
767
  }
768
+ }
769
+ #sync-container {
770
+ line-height: normal;
771
+ }
772
+
773
+ #sync-container #sync-button-slow {
774
+ display: none;
775
+ }
776
+
777
+ #sync-container.no-sse #sync-button-slow {
778
+ display: initial;
779
+ }
780
+
781
+ #sync-container.no-sse #sync-button {
782
+ display: none;
783
+ }
784
+
785
+ #sync-container .sync-block {
786
+ display: none;
787
+ }
788
+
789
+ #sync-container.state-initial #sync-button,
790
+ #sync-container.state-initial #last-sync-date,
791
+
792
+ #sync-container.state-in-progress #updating,
793
+ #sync-container.state-in-progress #update-progress,
794
+
795
+ #sync-container.state-complete #complete,
796
+ #sync-container.state-complete #last-sync-date,
797
+ #sync-container.state-complete #sync-error
798
+ {
799
+ display: block;
800
+ }
801
+
802
+ #sync-container #sync-error .message {
803
+ color: #d34f2b;
804
+ }
805
+
806
+ #sync-container #sync-button,
807
+ #sync-container #sync-button-slow {
808
+ cursor: pointer;
809
+ }
810
+
811
+ #sync-container #update-progress {
812
+ padding-left: 30px;
813
+ font-weight: 600;
814
+ }
815
+
816
+ #sync-container #complete {
817
+ font-weight: 600;
818
+ }
819
+
820
+ #sync-container #complete,
821
+ #sync-container #sync-button,
822
+ #sync-container #updating {
823
+ height: 3em;
824
+ }
825
+
826
+ #updating {
827
+ line-height: 26px;
828
+ color: #298CBA;
829
+ font-weight: 600;
830
+ }
831
+
832
+ #updating svg {
833
+ animation-name: rotation;
834
+ animation-duration: 1s;
835
+ animation-iteration-count: infinite;
836
+ animation-timing-function: linear;
837
+ display: inline-block;
838
+ vertical-align: middle;
839
+ }
840
+
841
+ #updating svg path {
842
+ fill: #298CBA;
843
+ }
844
+
845
+ .sync-block#updating > div {
846
+ display: table-cell;
847
+ vertical-align: middle;
848
+ }
849
+
850
+ .sync-block#updating {
851
+ line-height: initial;
852
+ }
853
+
854
+ .sync-block#updating .sync-icon {
855
+ width: 30px;
856
+ }
857
+
858
+ @keyframes rotation {
859
+ 0% {transform:rotate(0deg);}
860
+ 100% {transform:rotate(360deg);}
861
  }
ecwid-shopping-cart.php CHANGED
@@ -5,7 +5,7 @@ Plugin URI: http://www.ecwid.com?source=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 Team
8
- Version: 4.8
9
  Author URI: http://www.ecwid.com?source=wporg
10
  */
11
 
@@ -61,6 +61,8 @@ if ( is_admin() ){
61
  add_action('wp_ajax_ecwid_reset_categories_cache', 'ecwid_reset_categories_cache');
62
  add_action('wp_ajax_ecwid_create_store', 'ecwid_create_store');
63
  add_filter('plugin_action_links_' . ECWID_PLUGIN_BASENAME, 'ecwid_plugin_actions');
 
 
64
  add_action('admin_head', 'ecwid_ie8_fonts_inclusion');
65
  add_action('save_post', 'ecwid_save_post');
66
  add_action('init', 'ecwid_apply_theme', 0);
@@ -110,6 +112,7 @@ require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-message-manager.php';
110
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-store-editor.php';
111
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-product-popup.php';
112
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-oauth.php';
 
113
 
114
  if (is_admin()) {
115
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-help-page.php';
@@ -138,6 +141,16 @@ function ecwid_init_integrations()
138
  }
139
  }
140
 
 
 
 
 
 
 
 
 
 
 
141
  $version = get_bloginfo('version');
142
 
143
  function ecwid_add_breadcrumbs_navxt($trail)
@@ -271,6 +284,17 @@ function ecwid_enqueue_frontend() {
271
 
272
  wp_enqueue_script( 'ecwid-frontend-js', ECWID_PLUGIN_URL . 'js/frontend.js', array( 'jquery' ), get_option( 'ecwid_plugin_version' ) );
273
 
 
 
 
 
 
 
 
 
 
 
 
274
  if (is_active_widget(false, false, 'ecwidrecentlyviewed')) {
275
  wp_enqueue_script('ecwid-recently-viewed', ECWID_PLUGIN_URL . 'js/recently-viewed-common.js', array('jquery', 'utils'), get_option('ecwid_plugin_version'), true);
276
 
@@ -504,6 +528,8 @@ function ecwid_check_version()
504
  }
505
 
506
 
 
 
507
  add_option('ecwid_chameleon_colors_foreground', '');
508
  add_option('ecwid_chameleon_colors_background', '');
509
  add_option('ecwid_chameleon_colors_link', '');
@@ -514,14 +540,14 @@ function ecwid_check_version()
514
 
515
  function ecwid_get_woocommerce_status() {
516
 
517
- $woo = EcwidPlatform::cache_get('woo_status');
518
 
519
  if (is_null($woo)) {
520
  $woo = 0;
521
  $all_plugins = get_plugins();
522
  if (array_key_exists('woocommerce/woocommerce.php', $all_plugins)) {
523
  $active_plugins = get_option('active_plugins');
524
- if (in_array('woocommerce/woocommerce.php', $active_plugins)) {
525
  $woo = 2;
526
  } else {
527
  $woo = 1;
@@ -1069,7 +1095,11 @@ function ecwid_get_scriptjs_code($force_lang = null) {
1069
  if (!$ecwid_script_rendered) {
1070
  $store_id = get_ecwid_store_id();
1071
  $force_lang_str = !empty($force_lang) ? "&lang=$force_lang" : '';
1072
- $s = '<script data-cfasync="false" type="text/javascript" src="https://' . APP_ECWID_COM . '/script.js?' . $store_id . '&data_platform=wporg' . $force_lang_str . '"></script>';
 
 
 
 
1073
  $s = $s . ecwid_sso();
1074
  $s .= '<script type="text/javascript">if (jQuery && jQuery.mobile) { jQuery.mobile.hashListeningEnabled = false; jQuery.mobile.pushStateEnabled=false; }</script>';
1075
  $ecwid_script_rendered = true;
@@ -1374,6 +1404,9 @@ EOT;
1374
 
1375
  Ecwid_Nav_Menus::add_menu_on_activate();
1376
 
 
 
 
1377
  Ecwid_Message_Manager::enable_message('on_activate');
1378
  }
1379
 
@@ -1428,6 +1461,9 @@ function ecwid_store_deactivate() {
1428
  }
1429
 
1430
  Ecwid_Message_Manager::reset_hidden_messages();
 
 
 
1431
  }
1432
 
1433
  function ecwid_uninstall() {
@@ -1613,12 +1649,26 @@ function ecwid_build_menu() {
1613
  'manage_options', 'ecwid-help', 'ecwid_help_do_page'
1614
  );
1615
  add_submenu_page('', 'Install ecwid theme', '', 'manage_options', 'ecwid-install-theme', 'ecwid_install_theme');
 
 
 
 
 
 
 
 
 
 
 
 
 
1616
  }
1617
 
1618
  function ecwid_get_categories($nocache = false) {
1619
  $categories = EcwidPlatform::cache_get('all_categories');
1620
 
1621
  if ( false == $categories || $nocache ) {
 
1622
  $request = Ecwid_Http::create_get(
1623
  'get_categories_through_endpoint',
1624
  ecwid_get_categories_js_url(),
@@ -1700,7 +1750,7 @@ function ecwid_plugin_actions($links) {
1700
 
1701
  function ecwid_settings_api_init() {
1702
 
1703
- if ( isset( $_POST['settings_section'] ) ) {
1704
  switch ( $_POST['settings_section'] ) {
1705
  case 'appearance':
1706
  register_setting( 'ecwid_options_page', 'ecwid_enable_minicart' );
@@ -1734,6 +1784,12 @@ function ecwid_settings_api_init() {
1734
  break;
1735
  }
1736
 
 
 
 
 
 
 
1737
  if ($_POST['settings_section'] == 'advanced' && !@$_POST['ecwid_is_sso_enabled']) {
1738
  update_option('ecwid_sso_secret_key', '');
1739
  }
@@ -1744,6 +1800,8 @@ function ecwid_settings_api_init() {
1744
  update_option('ecwid_api_check_time', 0);
1745
  update_option('ecwid_last_oauth_fail_time', 0);
1746
  }
 
 
1747
  }
1748
 
1749
  function ecwid_common_admin_scripts() {
@@ -1762,6 +1820,8 @@ function ecwid_common_admin_scripts() {
1762
  'cache_updated' => __('Done', 'ecwid-shopping-cart'),
1763
  'reset_cache_message' => __('The store top-level categories are automatically added to this drop-down menu', 'ecwid-shopping-cart'),
1764
  ));
 
 
1765
  }
1766
 
1767
  function ecwid_get_register_link()
@@ -1796,10 +1856,11 @@ function ecwid_get_register_link()
1796
  function ecwid_create_store() {
1797
  $api = new Ecwid_Api_V3();
1798
  $result = $api->create_store();
 
1799
  if ( is_array( $result ) && $result['response']['code'] == 200 ) {
1800
  $data = json_decode( $result['body'] );
1801
 
1802
- update_option( 'ecwid_store_id', $data->id );
1803
 
1804
  $api->save_token( $data->token );
1805
  update_option( 'ecwid_oauth_scope', 'read_profile read_catalog allow_sso create_customers public_storefront' );
@@ -1912,6 +1973,12 @@ function ecwid_general_settings_do_page() {
1912
 
1913
  function ecwid_get_iframe_src($time, $page) {
1914
 
 
 
 
 
 
 
1915
  return sprintf(
1916
  'https://my.ecwid.com/api/v3/%s/sso?token=%s&timestamp=%s&signature=%s&place=%s&inline&lang=%s&min-height=700',
1917
  get_ecwid_store_id(),
@@ -1919,7 +1986,7 @@ function ecwid_get_iframe_src($time, $page) {
1919
  $time,
1920
  hash( 'sha256', get_ecwid_store_id() . Ecwid_Api_V3::get_token() . $time . Ecwid_Api_V3::CLIENT_SECRET ),
1921
  $page,
1922
- substr( get_bloginfo( 'language' ), 0, 2 )
1923
  );
1924
  }
1925
 
@@ -2116,11 +2183,15 @@ function ecwid_advanced_settings_do_page() {
2116
  $is_sso_checkbox_disabled = true;
2117
  }
2118
 
2119
- $reconnect_link = admin_url('admin-post.php?action=ecwid_connect&reconnect&api_v3_sso');
2120
 
2121
  require_once ECWID_PLUGIN_DIR . 'templates/advanced-settings.php';
2122
  }
2123
 
 
 
 
 
2124
  function ecwid_get_admin_iframe_upgrade_page() {
2125
  return 'billing:feature=sso&plan=ecwid_venture';
2126
  }
@@ -2180,6 +2251,165 @@ function get_ecwid_store_id() {
2180
  return $store_id;
2181
  }
2182
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2183
  function ecwid_save_post($post_id)
2184
  {
2185
  // If primary or auto store page gets updated
@@ -2381,8 +2611,6 @@ JS;
2381
 
2382
  $ecwid_sso_profile = "$user_data_encoded $hmac $time";
2383
 
2384
-
2385
- //die(var_dump($user_data, json_encode($user_data), $ecwid_sso_profile));
2386
  }
2387
 
2388
 
@@ -2442,6 +2670,14 @@ function ecwid_get_default_pb_size() {
2442
  );
2443
  }
2444
 
 
 
 
 
 
 
 
 
2445
  function ecwid_is_paid_account()
2446
  {
2447
  return ecwid_is_api_enabled() && get_ecwid_store_id() != ECWID_DEMO_STORE_ID;
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 Team
8
+ Version: 4.9
9
  Author URI: http://www.ecwid.com?source=wporg
10
  */
11
 
61
  add_action('wp_ajax_ecwid_reset_categories_cache', 'ecwid_reset_categories_cache');
62
  add_action('wp_ajax_ecwid_create_store', 'ecwid_create_store');
63
  add_filter('plugin_action_links_' . ECWID_PLUGIN_BASENAME, 'ecwid_plugin_actions');
64
+ add_action('admin_post_ecwid_sync_products', 'ecwid_sync_products');
65
+ add_action('wp_ajax_ecwid_sync_products', 'ecwid_sync_products');
66
  add_action('admin_head', 'ecwid_ie8_fonts_inclusion');
67
  add_action('save_post', 'ecwid_save_post');
68
  add_action('init', 'ecwid_apply_theme', 0);
112
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-store-editor.php';
113
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-product-popup.php';
114
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-oauth.php';
115
+ require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-products.php';
116
 
117
  if (is_admin()) {
118
  require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-help-page.php';
141
  }
142
  }
143
 
144
+ add_action('admin_post_ecwid_estimate_sync', 'ecwid_estimate_sync');
145
+
146
+ function ecwid_estimate_sync() {
147
+ $p = new Ecwid_Products();
148
+
149
+ $result = $p->estimate_sync();
150
+
151
+ echo json_encode($result);
152
+ }
153
+
154
  $version = get_bloginfo('version');
155
 
156
  function ecwid_add_breadcrumbs_navxt($trail)
284
 
285
  wp_enqueue_script( 'ecwid-frontend-js', ECWID_PLUGIN_URL . 'js/frontend.js', array( 'jquery' ), get_option( 'ecwid_plugin_version' ) );
286
 
287
+ if ( get_post()->post_type == Ecwid_Products::POST_TYPE_PRODUCT ) {
288
+ wp_enqueue_script( 'ecwid-post-product', ECWID_PLUGIN_URL . 'js/post-product.js', array(), get_option( 'ecwid_plugin_version' ), TRUE );
289
+
290
+ $meta = get_post_meta(get_the_ID(), 'ecwid_id');
291
+
292
+ wp_localize_script( 'ecwid-post-product', 'ecwidPost', array(
293
+ 'productId' => $meta[0],
294
+ 'storePageUrl' => ecwid_get_store_page_url()
295
+ ) );
296
+ }
297
+
298
  if (is_active_widget(false, false, 'ecwidrecentlyviewed')) {
299
  wp_enqueue_script('ecwid-recently-viewed', ECWID_PLUGIN_URL . 'js/recently-viewed-common.js', array('jquery', 'utils'), get_option('ecwid_plugin_version'), true);
300
 
528
  }
529
 
530
 
531
+ add_option( Ecwid_Products::OPTION_ENABLED, Ecwid_Products::is_enabled() );
532
+
533
  add_option('ecwid_chameleon_colors_foreground', '');
534
  add_option('ecwid_chameleon_colors_background', '');
535
  add_option('ecwid_chameleon_colors_link', '');
540
 
541
  function ecwid_get_woocommerce_status() {
542
 
543
+ $woo = EcwidPlatform::cache_get('woo_status', null);
544
 
545
  if (is_null($woo)) {
546
  $woo = 0;
547
  $all_plugins = get_plugins();
548
  if (array_key_exists('woocommerce/woocommerce.php', $all_plugins)) {
549
  $active_plugins = get_option('active_plugins');
550
+ if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', $active_plugins))) {
551
  $woo = 2;
552
  } else {
553
  $woo = 1;
1095
  if (!$ecwid_script_rendered) {
1096
  $store_id = get_ecwid_store_id();
1097
  $force_lang_str = !empty($force_lang) ? "&lang=$force_lang" : '';
1098
+ $params = '&data_platform=wporg' . $force_lang_str;
1099
+ if ( Ecwid_Products::is_enabled() ) {
1100
+ $params .= '&data_sync_products=1';
1101
+ }
1102
+ $s = '<script data-cfasync="false" type="text/javascript" src="https://' . APP_ECWID_COM . '/script.js?' . $store_id . $params . '"></script>';
1103
  $s = $s . ecwid_sso();
1104
  $s .= '<script type="text/javascript">if (jQuery && jQuery.mobile) { jQuery.mobile.hashListeningEnabled = false; jQuery.mobile.pushStateEnabled=false; }</script>';
1105
  $ecwid_script_rendered = true;
1404
 
1405
  Ecwid_Nav_Menus::add_menu_on_activate();
1406
 
1407
+ $p = new Ecwid_Products();
1408
+ $p->enable_all_products();
1409
+
1410
  Ecwid_Message_Manager::enable_message('on_activate');
1411
  }
1412
 
1461
  }
1462
 
1463
  Ecwid_Message_Manager::reset_hidden_messages();
1464
+
1465
+ $p = new Ecwid_Products();
1466
+ $p->disable_all_products();
1467
  }
1468
 
1469
  function ecwid_uninstall() {
1649
  'manage_options', 'ecwid-help', 'ecwid_help_do_page'
1650
  );
1651
  add_submenu_page('', 'Install ecwid theme', '', 'manage_options', 'ecwid-install-theme', 'ecwid_install_theme');
1652
+
1653
+ add_submenu_page('', 'Ecwid sync', '', 'manage_options', 'ecwid-sync', 'ecwid_sync_do_page');
1654
+ }
1655
+
1656
+ function ecwid_sync_do_page() {
1657
+
1658
+ require_once ECWID_PLUGIN_DIR . 'includes/class-ecwid-products.php';
1659
+
1660
+ $prods = new Ecwid_Products();
1661
+
1662
+ $estimation = $prods->estimate_sync();
1663
+
1664
+ require_once ECWID_PLUGIN_DIR . 'templates/sync.php';
1665
  }
1666
 
1667
  function ecwid_get_categories($nocache = false) {
1668
  $categories = EcwidPlatform::cache_get('all_categories');
1669
 
1670
  if ( false == $categories || $nocache ) {
1671
+
1672
  $request = Ecwid_Http::create_get(
1673
  'get_categories_through_endpoint',
1674
  ecwid_get_categories_js_url(),
1750
 
1751
  function ecwid_settings_api_init() {
1752
 
1753
+ if ( isset( $_POST['settings_section'] ) ) {
1754
  switch ( $_POST['settings_section'] ) {
1755
  case 'appearance':
1756
  register_setting( 'ecwid_options_page', 'ecwid_enable_minicart' );
1784
  break;
1785
  }
1786
 
1787
+ if ($_POST['settings_section'] == 'advanced' && isset($_POST[Ecwid_Products::OPTION_ENABLED]) && !Ecwid_Products::is_enabled()) {
1788
+ Ecwid_Products::enable();
1789
+ } else if ($_POST['settings_section'] == 'advanced' && !isset($_POST[Ecwid_Products::OPTION_ENABLED]) && Ecwid_Products::is_enabled()) {
1790
+ Ecwid_Products::disable();
1791
+ }
1792
+
1793
  if ($_POST['settings_section'] == 'advanced' && !@$_POST['ecwid_is_sso_enabled']) {
1794
  update_option('ecwid_sso_secret_key', '');
1795
  }
1800
  update_option('ecwid_api_check_time', 0);
1801
  update_option('ecwid_last_oauth_fail_time', 0);
1802
  }
1803
+
1804
+
1805
  }
1806
 
1807
  function ecwid_common_admin_scripts() {
1820
  'cache_updated' => __('Done', 'ecwid-shopping-cart'),
1821
  'reset_cache_message' => __('The store top-level categories are automatically added to this drop-down menu', 'ecwid-shopping-cart'),
1822
  ));
1823
+
1824
+ wp_enqueue_script('ecwid-sync', ECWID_PLUGIN_URL . 'js/sync.js', array(), get_option('ecwid_plugin_version'));
1825
  }
1826
 
1827
  function ecwid_get_register_link()
1856
  function ecwid_create_store() {
1857
  $api = new Ecwid_Api_V3();
1858
  $result = $api->create_store();
1859
+
1860
  if ( is_array( $result ) && $result['response']['code'] == 200 ) {
1861
  $data = json_decode( $result['body'] );
1862
 
1863
+ ecwid_update_store_id($data->id);
1864
 
1865
  $api->save_token( $data->token );
1866
  update_option( 'ecwid_oauth_scope', 'read_profile read_catalog allow_sso create_customers public_storefront' );
1973
 
1974
  function ecwid_get_iframe_src($time, $page) {
1975
 
1976
+ if (function_exists('get_user_locale')) {
1977
+ $lang = get_user_locale();
1978
+ } else {
1979
+ $lang = get_locale();
1980
+ }
1981
+
1982
  return sprintf(
1983
  'https://my.ecwid.com/api/v3/%s/sso?token=%s&timestamp=%s&signature=%s&place=%s&inline&lang=%s&min-height=700',
1984
  get_ecwid_store_id(),
1986
  $time,
1987
  hash( 'sha256', get_ecwid_store_id() . Ecwid_Api_V3::get_token() . $time . Ecwid_Api_V3::CLIENT_SECRET ),
1988
  $page,
1989
+ substr( $lang, 0, 2 )
1990
  );
1991
  }
1992
 
2183
  $is_sso_checkbox_disabled = true;
2184
  }
2185
 
2186
+ $reconnect_link = get_reconnect_link();
2187
 
2188
  require_once ECWID_PLUGIN_DIR . 'templates/advanced-settings.php';
2189
  }
2190
 
2191
+ function get_reconnect_link() {
2192
+ return admin_url('admin-post.php?action=ecwid_connect&reconnect&api_v3_sso');
2193
+ }
2194
+
2195
  function ecwid_get_admin_iframe_upgrade_page() {
2196
  return 'billing:feature=sso&plan=ecwid_venture';
2197
  }
2251
  return $store_id;
2252
  }
2253
 
2254
+ function ecwid_sync_products() {
2255
+
2256
+ set_time_limit(3600);
2257
+ if (!defined('DOING_AJAX')) {
2258
+ echo '<html><body>Lets begin<br />';
2259
+ flush();
2260
+ }
2261
+ $p = new Ecwid_Products();
2262
+ $p->sync();
2263
+
2264
+ if (defined('DOING_AJAX') && DOING_AJAX) {
2265
+ echo 'OK';
2266
+ wp_die();
2267
+ } else {
2268
+ wp_redirect('admin.php?page=ecwid-advanced');
2269
+ }
2270
+ }
2271
+
2272
+
2273
+ function ecwid_sync_progress_callback($status) {
2274
+ if (!@$status['event']) {
2275
+ $status['event'] = 'progress';
2276
+ }
2277
+
2278
+ echo 'event: ' . $status['event'] . "\n";
2279
+
2280
+ echo 'data: ' . json_encode($status) . "\n\n";
2281
+ flush();
2282
+ }
2283
+
2284
+ add_action('admin_post_ecwid_sync_sse', 'ecwid_sync_products_sse');
2285
+ function ecwid_sync_products_sse() {
2286
+ set_time_limit(0);
2287
+
2288
+ header("Content-Type: text/event-stream\n\n");
2289
+ Ecwid_Products::enable();
2290
+ $p = new Ecwid_Products();
2291
+
2292
+ $p->set_sync_progress_callback('ecwid_sync_progress_callback');
2293
+ $p->sync();
2294
+
2295
+ ecwid_sync_progress_callback(
2296
+ array(
2297
+ 'event' => 'completed',
2298
+ 'last_update' => ecwid_format_date( $p->get_last_sync_time() )
2299
+ )
2300
+ );
2301
+ }
2302
+
2303
+ function ecwid_format_date( $unixtime ) {
2304
+ return date( __( "Y/m/d g:i:s a" ), $unixtime );
2305
+ }
2306
+
2307
+ function ecwid_slow_sync_progress($status) {
2308
+ global $ecwid_sync_status;
2309
+ if (!Ecwid_Products::is_enabled()) {
2310
+ Ecwid_Products::enable();
2311
+ }
2312
+
2313
+ if (!isset($ecwid_sync_status)) {
2314
+ $ecwid_sync_status = array(
2315
+ 'limit' => -1,
2316
+ 'offset' => -1,
2317
+ 'total' => -1,
2318
+ 'count' => -1,
2319
+ 'updated' => 0,
2320
+ 'deleted_disabled' => 0,
2321
+ 'created' => 0,
2322
+ 'deleted' => 0,
2323
+ 'skipped_deleted' => 0
2324
+ );
2325
+ }
2326
+
2327
+ if ($status['event'] == 'fetching_products' || $status['event'] == 'fetching_deleted_product_ids') {
2328
+ $ecwid_sync_status['offset'] = $status['offset'];
2329
+ $ecwid_sync_status['limit'] = $status['limit'];
2330
+ } else if ($status['event'] == 'found_updated' || $status['event'] == 'found_deleted') {
2331
+ $ecwid_sync_status['total'] = $status['total'];
2332
+ $ecwid_sync_status['count'] = $status['count'];
2333
+
2334
+ } else if ($status['event'] == 'created_product') {
2335
+ $ecwid_sync_status['created']++;
2336
+ } else if ($status['event'] == 'updated_product') {
2337
+ $ecwid_sync_status['updated']++;
2338
+ } else if ($status['event'] == 'deleted_disabled_product') {
2339
+ $ecwid_sync_status['deleted_disabled']++;
2340
+ } else if ($status['event'] == 'deleted_product') {
2341
+ $ecwid_sync_status['deleted'] ++;
2342
+ } else if ($status['event'] == 'skipped_deleted') {
2343
+ $ecwid_sync_status['skipped_deleted']++;
2344
+ }
2345
+ }
2346
+
2347
+ add_action('admin_post_ecwid_sync_reset', 'ecwid_sync_reset');
2348
+
2349
+ function ecwid_sync_reset()
2350
+ {
2351
+ EcwidPlatform::set(Ecwid_Products_Sync_Status::OPTION_UPDATE_TIME, 0);
2352
+ EcwidPlatform::set(Ecwid_Products_Sync_Status::OPTION_LAST_PRODUCT_UPDATE_TIME, 0);
2353
+ EcwidPlatform::set(Ecwid_Products_Sync_Status::OPTION_LAST_PRODUCT_DELETE_TIME, 0);
2354
+
2355
+ wp_redirect('admin.php?page=ecwid-advanced');
2356
+ }
2357
+
2358
+ add_action('admin_post_ecwid_sync_no_sse', 'ecwid_sync_products_no_sse');
2359
+ function ecwid_sync_products_no_sse() {
2360
+ $p = new Ecwid_Products();
2361
+
2362
+ error_log(var_export($_GET, true));
2363
+
2364
+ $p->set_sync_progress_callback('ecwid_slow_sync_progress');
2365
+
2366
+ $over = $p->sync(array(
2367
+ 'mode' => $_GET['mode'] == 'deleted' ? 'deleted' : 'updated',
2368
+ 'offset' => intval($_GET['offset']),
2369
+ 'one_at_a_time' => true,
2370
+ 'from' => $_GET['time']
2371
+ ));
2372
+
2373
+ global $ecwid_sync_status;
2374
+
2375
+ if (!$over) {
2376
+ echo json_encode($ecwid_sync_status);
2377
+ } else {
2378
+ echo json_encode(array_merge($ecwid_sync_status, array('status' => 'complete', 'last_update' => ecwid_format_date( $p->get_last_sync_time() ))));
2379
+ }
2380
+ }
2381
+
2382
+ add_action('admin_post_ecwid_tick', 'ecwid_tick');
2383
+
2384
+ function ecwid_tick() {
2385
+
2386
+ var_dump(ini_get('max_execution_time'));
2387
+ set_time_limit(12345);
2388
+ var_dump(ini_get('max_execution_time'));
2389
+ error_log('tick');
2390
+ header("Content-Type: text/event-stream\n\n");
2391
+ for ($i = 0; $i < 30; $i++) {
2392
+ echo "data: $i \n\n";
2393
+ flush();
2394
+ sleep(2);
2395
+ //usleep(2000);
2396
+ }
2397
+ die();
2398
+ }
2399
+
2400
+
2401
+ function ecwid_dashboard_widget_function() {
2402
+ if (!is_ssl()) {
2403
+ require_once ECWID_PLUGIN_DIR . 'templates/wp-dashboard-widget.php';
2404
+ }
2405
+ }
2406
+
2407
+ function ecwid_add_dashboard_widgets() {
2408
+ if (current_user_can('manage_options')) {
2409
+ wp_add_dashboard_widget('ecwid_dashboard_widget', __('Recommendations for Your Online Store', 'ecwid-shopping-cart'), 'ecwid_dashboard_widget_function');
2410
+ }
2411
+ }
2412
+
2413
  function ecwid_save_post($post_id)
2414
  {
2415
  // If primary or auto store page gets updated
2611
 
2612
  $ecwid_sso_profile = "$user_data_encoded $hmac $time";
2613
 
 
 
2614
  }
2615
 
2616
 
2670
  );
2671
  }
2672
 
2673
+ function ecwid_update_store_id( $new_store_id ) {
2674
+ update_option( 'ecwid_store_id', $new_store_id );
2675
+ update_option( 'ecwid_is_api_enabled', 'off' );
2676
+ update_option( 'ecwid_api_check_time', 0 );
2677
+
2678
+ do_action('ecwid_update_store_id', $new_store_id);
2679
+ }
2680
+
2681
  function ecwid_is_paid_account()
2682
  {
2683
  return ecwid_is_api_enabled() && get_ecwid_store_id() != ECWID_DEMO_STORE_ID;
images/update.svg ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
5
+ width="26px" height="26px" viewBox="0 0 26 26" enable-background="new 0 0 26 26" xml:space="preserve">
6
+ <g>
7
+ <path fill="#343334" d="M5.835,13c0-3.615,2.683-6.599,6.165-7.087V8l6.399-4L12,0v2.238C6.499,2.743,2.188,7.367,2.188,13
8
+ c0,2.935,1.174,5.593,3.073,7.541l2.695-2.457C6.646,16.785,5.835,14.988,5.835,13z"/>
9
+ <path fill="#343334" d="M23.812,13c0-2.934-1.174-5.591-3.071-7.54l-2.694,2.458c1.307,1.298,2.117,3.095,2.117,5.082
10
+ c0,3.614-2.683,6.596-6.164,7.083V18l-6.4,4l6.4,4v-2.238C19.502,23.257,23.812,18.633,23.812,13z"/>
11
+ </g>
12
+ </svg>
includes/class-ecwid-oauth.php CHANGED
@@ -119,7 +119,8 @@ class Ecwid_OAuth {
119
  return $this->trigger_auth_error($reconnect ? 'reconnect' : 'default');
120
  }
121
 
122
- update_option( 'ecwid_store_id', $result->store_id );
 
123
  update_option( 'ecwid_oauth_scope', $result->scope );
124
  update_option( 'ecwid_api_check_time', 0 );
125
  EcwidPlatform::cache_reset( 'all_categories' );
119
  return $this->trigger_auth_error($reconnect ? 'reconnect' : 'default');
120
  }
121
 
122
+ ecwid_update_store_id( $result->store_id );
123
+
124
  update_option( 'ecwid_oauth_scope', $result->scope );
125
  update_option( 'ecwid_api_check_time', 0 );
126
  EcwidPlatform::cache_reset( 'all_categories' );
includes/class-ecwid-products.php ADDED
@@ -0,0 +1,677 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once ECWID_PLUGIN_DIR . '/lib/ecwid_api_v3.php';
4
+ require_once ECWID_PLUGIN_DIR . '/lib/ecwid_platform.php';
5
+
6
+ class Ecwid_Products {
7
+
8
+ protected $_api;
9
+ protected $_status;
10
+ protected $_sync_progress_callback;
11
+
12
+ const POST_TYPE_PRODUCT = 'ec-product';
13
+ const DB_ALIAS_OUT_OF_STOCK = 'ecwid_out_of_stock';
14
+ const OPTION_ENABLED = 'ecwid_local_base_enabled';
15
+
16
+ public function __construct() {
17
+
18
+ $this->_api = new Ecwid_Api_V3(get_ecwid_store_id());
19
+ $this->_status = new Ecwid_Products_Sync_Status();
20
+ $this->_status->load();
21
+
22
+ add_action( 'ecwid_update_store_id', array( $this, 'on_update_store_id' ) );
23
+
24
+ if ( ! self::is_enabled() ) {
25
+ return;
26
+ }
27
+
28
+ add_action( 'init', array($this, 'register_post_type' ) );
29
+ add_action( 'admin_init', array($this, 'register_post_type' ) );
30
+ add_filter( 'the_content', array( $this, 'content' ) );
31
+ add_filter( 'post_thumbnail_html', array( $this, 'thumbnail' ) );
32
+ add_action( 'wp_ajax_ecwid_get_post_link', array($this, 'ajax_get_post_link' ) );
33
+ add_action( 'wp_ajax_nopriv_ecwid_get_post_link', array($this, 'ajax_get_post_link' ) );
34
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend' ) );
35
+ add_filter( 'post_type_link', array( $this, 'replace_product_page_url_on_search' ), 10, 3 );
36
+ add_action( 'template_redirect', array( $this, 'redirect_to_store_page' ) );
37
+
38
+ if (EcwidPlatform::get('hide_out_of_stock')) {
39
+ add_filter( 'posts_where_paged', array( $this, 'where_out_of_stock' ) );
40
+ add_filter( 'posts_join_paged', array( $this, 'join_out_of_stock' ) );
41
+ }
42
+
43
+ $this->_sync_progress_callback = '__return_false';
44
+ }
45
+
46
+ public function enqueue_frontend() {
47
+ wp_enqueue_script('ecwid-product-page', ECWID_PLUGIN_URL . 'js/product.js', array('jquery'), get_option('ecwid_plugin_version'));
48
+ wp_localize_script('ecwid-product-page', 'ecwidProduct', array(
49
+ 'ajaxurl' => admin_url('admin-ajax.php')
50
+ ));
51
+ }
52
+
53
+ public function replace_product_page_url_on_search( $url, $post, $leavename = false ) {
54
+ if ( $post->post_type == self::POST_TYPE_PRODUCT && is_search() ) {
55
+ $new_url = $this->_get_post_link( $post->ID );
56
+
57
+ if ($new_url) {
58
+ return $new_url;
59
+ }
60
+ }
61
+
62
+ return $url;
63
+ }
64
+
65
+ public function redirect_to_store_page() {
66
+ $post = get_post();
67
+
68
+ if ( $post->post_type == self::POST_TYPE_PRODUCT && is_single() ) {
69
+ $url = $this->_get_post_link($post->ID);
70
+
71
+ if ($url) {
72
+ wp_redirect($url);
73
+ exit();
74
+ }
75
+ }
76
+ }
77
+
78
+
79
+ public function where_out_of_stock($where) {
80
+ if (!is_search()) {
81
+ return $where;
82
+ }
83
+ $where .= ' AND ' . self::DB_ALIAS_OUT_OF_STOCK . '.meta_value=1 ';
84
+
85
+ return $where;
86
+ }
87
+
88
+ public function join_out_of_stock($join) {
89
+ if (!is_search()) {
90
+ return $join;
91
+ }
92
+
93
+ if (!$join) {
94
+ $join = '';
95
+ }
96
+
97
+ global $wpdb;
98
+
99
+ $join .= 'LEFT JOIN ' . $wpdb->postmeta .' ' . self::DB_ALIAS_OUT_OF_STOCK
100
+ . ' ON ' . $wpdb->posts . '.id = ' . self::DB_ALIAS_OUT_OF_STOCK . '.post_id'
101
+ . ' AND ' . self::DB_ALIAS_OUT_OF_STOCK . '.meta_key=' . '"in_stock"';
102
+
103
+ return $join;
104
+ }
105
+
106
+
107
+
108
+ public function ajax_get_post_link() {
109
+
110
+ if ( !isset( $_REQUEST['product_id'] ) ) {
111
+ return;
112
+ }
113
+
114
+ $product_id = intval( @$_REQUEST['product_id'] );
115
+
116
+ $url = $this->_get_post_link();
117
+ $post_id = $this->_find_post_by_product_id( $product_id );
118
+
119
+ if ($post_id) {
120
+ echo json_encode( $this->_get_post_link( $post_id ) );
121
+ }
122
+
123
+ exit();
124
+ }
125
+
126
+ protected function _get_post_link( $post_id ) {
127
+
128
+ $store_page_url = ecwid_get_store_page_url();
129
+
130
+ if (! $store_page_url) {
131
+ return '';
132
+ }
133
+
134
+ $url = get_post_meta( $post_id, '_ecwid_url' );
135
+ $url = ecwid_get_store_page_url() . $url[0];
136
+
137
+ return $url;
138
+ }
139
+
140
+
141
+ public function on_update_store_id() {
142
+ $this->_status->reset_dates();
143
+ }
144
+
145
+ public function set_sync_progress_callback($callback) {
146
+ $this->_sync_progress_callback = $callback;
147
+ }
148
+
149
+ public function content($content) {
150
+
151
+ if ( get_post_type() == self::POST_TYPE_PRODUCT ) {
152
+
153
+ $ecwid_id = get_post_meta(get_the_ID(), 'ecwid_id');
154
+ $ecwid_id = $ecwid_id[0];
155
+
156
+ if (is_singular()) {
157
+ ob_start();
158
+ require ECWID_PLUGIN_DIR . '/templates/product.php';
159
+
160
+ $contents = ob_get_contents();
161
+ ob_end_clean();
162
+
163
+ return $contents;
164
+ }
165
+ }
166
+
167
+ return $content;
168
+ }
169
+
170
+ public function thumbnail($html) {
171
+
172
+ if (get_post_type() == self::POST_TYPE_PRODUCT && is_singular()) {
173
+ return '';
174
+ }
175
+
176
+ return $html;
177
+ }
178
+
179
+
180
+ public static function is_enabled() {
181
+ return get_option( self::OPTION_ENABLED, false );
182
+ }
183
+
184
+ public static function enable() {
185
+ flush_rewrite_rules(true);
186
+ update_option( self::OPTION_ENABLED, 1 );
187
+ }
188
+
189
+ public static function disable() {
190
+ flush_rewrite_rules(true);
191
+ update_option( self::OPTION_ENABLED, false );
192
+ }
193
+
194
+ public static function reset_sync_date() {
195
+ Ecwid_Products_Sync_Status::reset_dates();
196
+ }
197
+
198
+ public function register_post_type() {
199
+
200
+ register_post_type( self::POST_TYPE_PRODUCT,
201
+ array(
202
+ 'public' => TRUE,
203
+ 'capability_type' => 'product',
204
+ 'map_meta_cap' => TRUE,
205
+ 'publicly_queryable' => TRUE,
206
+ 'exclude_from_search' => FALSE,
207
+ 'hierarchical' => FALSE,
208
+ 'show_in_nav_menus' => TRUE,
209
+ 'show_ui' => false
210
+ )
211
+ );
212
+ }
213
+
214
+
215
+ public function is_in_sync() {
216
+ $stats = $this->_api->get_store_update_stats();
217
+
218
+ $update_time = strtotime($stats->productsUpdated);
219
+
220
+ $last_update = EcwidPlatform::get(self::OPTION_UPDATE_TIME);
221
+
222
+ return $last_update > $update_time;
223
+ }
224
+
225
+ public function set_last_update_time($time) {
226
+ EcwidPlatform::set(self::OPTION_UPDATE_TIME, $time);
227
+ }
228
+
229
+ public function get_last_sync_time() {
230
+ return $this->_status->get_last_sync_time();
231
+ }
232
+
233
+ public function estimate_sync() {
234
+
235
+ $updated = $this->_api->search_products( array(
236
+ 'updatedFrom' => $this->_status->get_updated_from(),
237
+ 'limit' => 1,
238
+ 'offset' => 0,
239
+ 'sortBy' => 'UPDATED_TIME_ASC'
240
+ ) );
241
+
242
+
243
+ $deleted = $this->_api->get_deleted_products( array(
244
+ 'from_date' => $this->_status->get_deleted_from(),
245
+ 'limit' => 1,
246
+ 'offset' => 0
247
+ ) );
248
+
249
+ $result = array(
250
+ 'total_deleted' => $deleted->total,
251
+ 'total_updated' => $updated->total
252
+ );
253
+
254
+ $result['last_update_string'] = Ecwid_Api_V3::format_time($this->_status->get_last_sync_time());
255
+ $result['last_update'] = $this->_status->get_last_sync_time();
256
+
257
+ if ($updated->total > 0) {
258
+ $result['updated_from'] = $updated->items[0]->updated;
259
+ $result['last_updated'] = Ecwid_Api_V3::format_time($this->_status->last_deleted_product_time);
260
+ }
261
+
262
+ if ($deleted->total > 0) {
263
+ $result['deleted_from'] = $deleted->items[0]->date;
264
+ $result['last_deleted'] = Ecwid_Api_V3::format_time($this->_status->last_deleted_product_time);
265
+ }
266
+
267
+ $api = new Ecwid_Api_V3();
268
+ $profile = $api->get_store_profile();
269
+
270
+ if ($profile && $profile->settings) {
271
+ EcwidPlatform::set('hide_out_of_stock', $profile->settings->hideOutOfStockProductsInStorefront);
272
+ }
273
+
274
+ return $result;
275
+ }
276
+
277
+ public function sync($settings = null) {
278
+
279
+ $did_something = false;
280
+
281
+ if (!$settings || $settings['mode'] == 'deleted') {
282
+ $did_something = $this->_process_deleted_products( $settings );
283
+ }
284
+
285
+ if (!$settings || $settings['one_at_a_time'] && !$did_something) {
286
+ $did_something = $this->_process_products($settings);
287
+ }
288
+
289
+ if (!$settings || $settings['one_at_a_time'] && !$did_something) {
290
+
291
+ $this->_status->update_last_sync_time( time() );
292
+
293
+ return true;
294
+ }
295
+
296
+ return false;
297
+ }
298
+
299
+ public function delete_all_products() {
300
+ global $wpdb;
301
+
302
+ $result = $wpdb->get_col( $wpdb->prepare(
303
+ "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '%s'", 'ecwid_id'
304
+ ));
305
+
306
+ foreach ($result as $post_id) {
307
+ wp_delete_post($post_id);
308
+ }
309
+ }
310
+
311
+ public function disable_all_products() {
312
+ global $wpdb;
313
+
314
+ $result = $wpdb->get_col( $wpdb->prepare(
315
+ "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '%s'", 'ecwid_id'
316
+ ));
317
+
318
+ foreach ($result as $post_id) {
319
+ wp_update_post(array(
320
+ 'ID' => $post_id,
321
+ 'post_status' => 'draft'
322
+ ));
323
+ }
324
+ }
325
+
326
+ public function enable_all_products() {
327
+ global $wpdb;
328
+
329
+ $result = $wpdb->get_col( $wpdb->prepare(
330
+ "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '%s'", 'ecwid_id'
331
+ ));
332
+
333
+ foreach ($result as $post_id) {
334
+ wp_update_post(array(
335
+ 'ID' => $post_id,
336
+ 'post_status' => 'publish'
337
+ ));
338
+ }
339
+ }
340
+
341
+ protected function _process_products($settings) {
342
+ $over = FALSE;
343
+
344
+ $offset = 0;
345
+ $limit = 100;
346
+ if ($settings && @$settings['offset']) {
347
+ $offset = $settings['offset'];
348
+ }
349
+
350
+ if ($settings && $settings['from']) {
351
+ $updated_from = $settings['from'];
352
+ } else {
353
+ $updated_from = $this->_status->get_updated_from();
354
+ }
355
+
356
+ while ( ! $over ) {
357
+
358
+ $this->_status_event(array(
359
+ 'event' => 'fetching_products',
360
+ 'offset' => $offset,
361
+ 'limit' => $limit
362
+ ));
363
+
364
+ $params = array(
365
+ 'updatedFrom' => $updated_from,
366
+ 'limit' => $limit,
367
+ 'offset' => $offset,
368
+ 'sortBy' => 'UPDATED_TIME_ASC'
369
+ );
370
+
371
+ $products = $this->_api->search_products( $params );
372
+
373
+ $this->_status_event(
374
+ array_merge(
375
+ $params,
376
+ array(
377
+ 'event' => 'found_updated',
378
+ 'total' => $products->total,
379
+ 'count' => $products->count
380
+ )
381
+ )
382
+ );
383
+
384
+ if ( $products->total == 0 || $products->count == 0 ) {
385
+ $over = TRUE;
386
+ return false;
387
+ }
388
+
389
+ foreach ( $products->items as $product ) {
390
+ $this->_process_product( $product );
391
+ }
392
+
393
+ if ( $products->total < $offset + $limit || @$settings['one_at_a_time'] ) {
394
+ break;
395
+ }
396
+
397
+ $offset += $limit;
398
+ }
399
+
400
+ return true;
401
+ }
402
+
403
+ protected function _find_post_by_product_id($product_id) {
404
+ global $wpdb;
405
+
406
+ $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->postmeta WHERE meta_key = '%s' AND meta_value = '%s' LIMIT 1", 'ecwid_id', $product_id ) );
407
+
408
+ $id = null;
409
+ if (!empty($row)) {
410
+ $id = $row->post_id;
411
+ }
412
+
413
+ return $id;
414
+ }
415
+
416
+ protected function _process_product( $product ) {
417
+
418
+ $id = $this->_find_post_by_product_id( $product->id );
419
+
420
+ if ( !$product->enabled ) {
421
+ if ( !is_null( $id ) ) {
422
+ wp_delete_post( $id );
423
+ }
424
+
425
+ $this->_status_event(
426
+ array(
427
+ 'event' => 'deleted_disabled_product',
428
+ 'product' => $product
429
+ )
430
+ );
431
+
432
+ return null;
433
+ }
434
+
435
+ return $this->_sync_product( $product, $id );
436
+ }
437
+
438
+ protected function _sync_product( $product, $existing_post_id = null ) {
439
+
440
+ $meta = array(
441
+ '_price' => $product->price,
442
+ '_regular_price' => $product->price,
443
+ 'image' => $product->imageUrl,
444
+ 'ecwid_id' => $product->id,
445
+ '_sku' => $product->sku,
446
+ '_visibility' => 'visible',
447
+ '_ecwid_url' => substr( $product->url, strpos( $product->url, '#!' ) ),
448
+ 'in_stock' => $product->inStock ? '1' : '0',
449
+ '_updatedTimestamp' => $product->updateTimestamp,
450
+ );
451
+
452
+ $post_id = wp_insert_post(
453
+ array(
454
+ 'ID' => $existing_post_id,
455
+ 'post_title' => $product->name,
456
+ 'post_content' => $product->description,
457
+ 'post_type' => self::POST_TYPE_PRODUCT,
458
+ 'post_status' => 'publish'
459
+ )
460
+ );
461
+
462
+ foreach ($meta as $key => $value) {
463
+ add_post_meta($post_id, $key, $value, true);
464
+ }
465
+
466
+ $image_id = get_post_meta( $post_id, '_thumbnail_id' );
467
+
468
+ if ( ! $image_id ) {
469
+ $this->_upload_product_thumbnail( $product, $post_id );
470
+ }
471
+
472
+ $this->_status->update_last_updated($product->updateTimestamp);
473
+
474
+ $this->_status_event(
475
+ array(
476
+ 'event' => $existing_post_id ? 'updated_product' : 'created_product',
477
+ 'product' => $product
478
+ )
479
+ );
480
+
481
+ return $post_id;
482
+ }
483
+
484
+ protected function _process_deleted_products($settings = array()) {
485
+ $over = FALSE;
486
+
487
+ $offset = 0;
488
+ $limit = 100;
489
+
490
+ if ($settings && @$settings['offset']) {
491
+ $offset = $settings['offset'];
492
+ }
493
+
494
+ if ($settings && $settings['from']) {
495
+ $deleted_from = $settings['from'];
496
+ } else {
497
+ $deleted_from = $this->_status->get_updated_from();
498
+ }
499
+
500
+ $deleted_from = $this->_status->get_deleted_from();
501
+ while ( ! $over ) {
502
+
503
+ $this->_status_event(array(
504
+ 'event' => 'fetching_deleted_product_ids',
505
+ 'offset' => $offset,
506
+ 'limit' => $limit
507
+ ));
508
+
509
+ $params = array(
510
+ 'from_date' => $deleted_from,
511
+ 'limit' => $limit,
512
+ 'offset' => $offset
513
+ );
514
+
515
+ $products = $this->_api->get_deleted_products( $params );
516
+
517
+ $this->_status_event(
518
+ array_merge(
519
+ $params,
520
+
521
+ array(
522
+ 'event' => 'found_deleted',
523
+ 'total' => $products->total,
524
+ 'count' => $products->count
525
+ )
526
+ )
527
+ );
528
+
529
+ if ( $products->total == 0 ) {
530
+ $over = TRUE;
531
+ return false;
532
+ }
533
+
534
+ foreach ( $products->items as $product ) {
535
+ $post_id = $this->_find_post_by_product_id($product->id);
536
+
537
+ if ($post_id) {
538
+ wp_delete_post( $post_id );
539
+ $this->_status_event(
540
+ array(
541
+ 'event' => 'deleted_product',
542
+ 'product' => $product
543
+ )
544
+ );
545
+ } else {
546
+ $this->_status_event(
547
+ array(
548
+ 'event' => 'skipped_deleted',
549
+ 'product' => $product
550
+ )
551
+ );
552
+ }
553
+
554
+ $this->_status->update_last_deleted($product->date);
555
+ }
556
+
557
+ if ( $products->total < $offset + $limit || @$settings['one_at_a_time'] ) {
558
+ return true;
559
+ }
560
+
561
+ $offset += $limit;
562
+ }
563
+ }
564
+
565
+ protected function _status_event($event) {
566
+ if ($this->_sync_progress_callback) {
567
+ call_user_func($this->_sync_progress_callback, $event);
568
+ }
569
+ }
570
+
571
+ protected function _upload_product_thumbnail( $product, $post_id ) {
572
+ $file = download_url( $product->imageUrl );
573
+
574
+ if (is_wp_error($file)) return;
575
+
576
+ $uploaded = wp_upload_bits( basename( $product->imageUrl ), NULL, file_get_contents( $file ) );
577
+ unlink( $file );
578
+
579
+ $filetype = wp_check_filetype( $uploaded['file'], NULL );
580
+ $file = $uploaded['file'];
581
+
582
+ $wp_upload_dir = wp_upload_dir();
583
+ $attachment = array(
584
+ 'guid' => $wp_upload_dir['url'] . '/' . basename( $file ),
585
+ 'post_mime_type' => $filetype['type'],
586
+ 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $file ) ),
587
+ 'post_content' => '',
588
+ 'post_status' => 'inherit'
589
+ );
590
+
591
+ $attachment_id = wp_insert_attachment( $attachment, $file, $post_id );
592
+ $attach_data = wp_generate_attachment_metadata( $attachment_id, $file );
593
+ wp_update_attachment_metadata( $attachment_id, $attach_data );
594
+ set_post_thumbnail( $post_id, $attachment_id );
595
+ }
596
+ }
597
+
598
+ class Ecwid_Products_Sync_Status {
599
+
600
+ const OPTION_UPDATE_TIME = 'update_time';
601
+ const OPTION_LAST_PRODUCT_UPDATE_TIME = 'last_product_update_time';
602
+ const OPTION_LAST_PRODUCT_DELETE_TIME = 'last_product_delete_time';
603
+ const OPTION_LAST_UPDATED_POST_ID = 'last_updated_post_id';
604
+
605
+ public $last_sync_time;
606
+ public $last_updated_product_time;
607
+ public $last_deleted_product_time;
608
+ public $current_operation;
609
+ public $error;
610
+ protected $_last_updated_post_id;
611
+
612
+ public function load() {
613
+ $this->last_sync_time = EcwidPlatform::get(self::OPTION_UPDATE_TIME, 0);
614
+ $this->last_updated_product_time = EcwidPlatform::get(self::OPTION_LAST_PRODUCT_UPDATE_TIME, 0);
615
+ $this->last_deleted_product_time = EcwidPlatform::get(self::OPTION_LAST_PRODUCT_DELETE_TIME, 0);
616
+ }
617
+
618
+ public function get_last_sync_time() {
619
+ return $this->last_sync_time;
620
+ }
621
+
622
+ public function update_last_sync_time($date) {
623
+ $this->_set_date_option(self::OPTION_UPDATE_TIME, $date);
624
+ $this->last_sync_time = $date;
625
+ $this->update_last_deleted($date);
626
+ $this->update_last_updated($date);
627
+ }
628
+
629
+ public function update_last_deleted($date) {
630
+ $this->_set_date_option(self::OPTION_LAST_PRODUCT_DELETE_TIME, $date);
631
+ }
632
+
633
+ public function set_last_updated_post_id($id) {
634
+ EcwidPlatform::set(self::OPTION_LAST_UPDATED_POST_ID, $id);
635
+ }
636
+
637
+ public function update_last_updated($date) {
638
+ $this->_set_date_option(self::OPTION_LAST_PRODUCT_UPDATE_TIME, $date);
639
+ }
640
+
641
+ public function get_updated_from() {
642
+
643
+ if (!$this->last_updated_product_time) {
644
+ return $this->get_last_sync_time();
645
+ }
646
+
647
+ return $this->last_updated_product_time;
648
+ }
649
+
650
+ public function get_deleted_from() {
651
+ if (!$this->last_deleted_product_time) {
652
+ return $this->get_last_sync_time();
653
+ }
654
+
655
+ return $this->last_deleted_product_time;
656
+ }
657
+
658
+ public function _set_date_option($option, $date) {
659
+ if (!is_int($date)) {
660
+ $date = strtotime($date);
661
+ }
662
+ EcwidPlatform::set($option, $date);
663
+ }
664
+
665
+ public static function reset_dates() {
666
+ foreach(
667
+ array(
668
+ self::OPTION_LAST_PRODUCT_DELETE_TIME,
669
+ self::OPTION_LAST_PRODUCT_UPDATE_TIME,
670
+ self::OPTION_UPDATE_TIME
671
+ ) as $option) {
672
+ EcwidPlatform::set($option, 0);
673
+ }
674
+ }
675
+ }
676
+
677
+ $p = new Ecwid_Products();
includes/widgets/class-ecwid-widget-recently-viewed.php CHANGED
@@ -67,7 +67,9 @@ class Ecwid_Widget_Recently_Viewed extends WP_Widget {
67
  $force_image = '';
68
  if ($api) {
69
  $product_https = $api->get_product_https($product->id);
70
- $force_image = $product_https['imageUrl'];
 
 
71
  }
72
 
73
  $name = isset($product_https) ? $product_https['name']: '';
67
  $force_image = '';
68
  if ($api) {
69
  $product_https = $api->get_product_https($product->id);
70
+ if ( isset( $product_https['imageUrl'] ) ) {
71
+ $force_image = $product_https['imageUrl'];
72
+ }
73
  }
74
 
75
  $name = isset($product_https) ? $product_https['name']: '';
js/post-product.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ Ecwid.OnPageLoad.add(function(page) {
2
+ debugger;
3
+ if ( page.type != 'PRODUCT' || page.productId != ecwidPost.productId ) {
4
+ location.href = ecwidPost.storePageUrl + location.hash;
5
+ }
6
+ });
js/product.js ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function() {
2
+ Ecwid.OnPageLoaded.add(function(page) {
3
+ if (page.type == 'PRODUCT') {
4
+
5
+ jQuery.getJSON(
6
+ ecwidProduct.ajaxurl,
7
+ {'action': 'ecwid_get_post_link', 'product_id': page.productId},
8
+ function(result) {
9
+ $canonical = jQuery('link[rel=canonical]');
10
+ if ($canonical.length == 0) {
11
+ $canonical = jQuery('<link rel="canonical">').appendTo('head');
12
+ }
13
+ $canonical.attr('href', result);
14
+ }
15
+ );
16
+ }
17
+ });
18
+ });
js/sync.js ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function() {
2
+ jQuery('#ecwid-sync-products').click(function() {
3
+ jQuery('#ecwid-sync-products-success, #ecwid-sync-products-error').hide();
4
+ jQuery('#ecwid-sync-products-inprogress').show();
5
+ jQuery.get('admin-ajax.php?action=ecwid_sync_products', {}, function($msg) {
6
+ jQuery('#ecwid-sync-products-inprogress').hide();
7
+ if ($msg == 'OK') {
8
+ jQuery('#ecwid-sync-products-success').show();
9
+ } else {
10
+ jQuery('#ecwid-sync-products-error').show();
11
+ }
12
+ });
13
+ });
14
+
15
+ });
languages/ecwid-shopping-cart-ru_RU.mo CHANGED
Binary file
languages/ecwid-shopping-cart-ru_RU.po CHANGED
@@ -457,8 +457,8 @@ msgstr "Здесь будет отображаться ваш магазин."
457
  msgid "Demo Store"
458
  msgstr "Демонстрационный магазин"
459
 
460
- msgid "Chameleon skin <sup>beta</sup>"
461
- msgstr "Тема \"Хамелеон\" <sup>бета</sup>"
462
 
463
  msgid "Automatic adjustment of your store design to your Wordpress theme. Whatever Wordpress theme you use, Ecwid will detect predominant colors and font and use them in your product catalog."
464
  msgstr "Автоматическая подстройка внешнего вида магазина под стили темы сайта. Включите эту опцию, чтобы Эквид определял цвета и шрифты сайта и использовал их в каталоге товаров."
@@ -817,4 +817,26 @@ msgstr "https://support.ecwid.com/hc/ru/sections/201706799-%D0%9F%D0%BE%D0%B4%D0
817
  msgid "https://support.ecwid.com/hc/en-us/sections/201702859-Technical-Reference"
818
  msgstr "https://support.ecwid.com/hc/ru/sections/201702859-%D0%A2%D0%B5%D1%85%D0%BD%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F-%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D1%8F"
819
 
 
 
820
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
457
  msgid "Demo Store"
458
  msgstr "Демонстрационный магазин"
459
 
460
+ msgid "Chameleon skin"
461
+ msgstr "Тема \"Хамелеон\""
462
 
463
  msgid "Automatic adjustment of your store design to your Wordpress theme. Whatever Wordpress theme you use, Ecwid will detect predominant colors and font and use them in your product catalog."
464
  msgstr "Автоматическая подстройка внешнего вида магазина под стили темы сайта. Включите эту опцию, чтобы Эквид определял цвета и шрифты сайта и использовал их в каталоге товаров."
817
  msgid "https://support.ecwid.com/hc/en-us/sections/201702859-Technical-Reference"
818
  msgstr "https://support.ecwid.com/hc/ru/sections/201702859-%D0%A2%D0%B5%D1%85%D0%BD%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F-%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D1%8F"
819
 
820
+ msgid "Integration with search on your site <sup>beta</sup>"
821
+ msgstr "Интеграция с поиском на сайте <sup>бета</sup>"
822
 
823
+ msgid "Ecwid stores your products data in a secure cloud storage. The product pages are displayed on the fly when a customer browses your store. So, basically, the products are not stored on the site, that's why the site search doesn't find product pages while looking through site pages and posts. This option enables a local storage mode: the products will be stored both in the cloud and on your site. The site search results will list product pages as well as regular pages/posts of your site."
824
+ msgstr "Эквид хранит данные товаров магазина в защищенном облачном хранилище, и показывает их прямо на странице магазина, когда посетитель открывает товар. Поэтому данные товаров не хранятся на вашем сайте, а поиск по сайту находит только страницы и записи сайта — не находит товары магазина. Эта настройка включает локальное хранение товаров: данные товаров будут храниться и в облачном хранилище, и прямо на вашем сайте. Поиск по сайту будет показывать страницы товаров магазина так же, как записи или страницы, размещенные на сайте."
825
+
826
+ msgid "Synchronize products"
827
+ msgstr "Синхронизировать товары"
828
+
829
+ msgid "Products are successfully synchronized. The product pages are up to date."
830
+ msgstr "Товары успешно синхронизированы. Страницы товаров обновлены."
831
+
832
+ msgid "Last update"
833
+ msgstr "Последняя синхронизация"
834
+
835
+ msgid "Please note this functionality is in beta. So if you run into difficulties or find problems with it, please <a %s>let us know</a>."
836
+ msgstr "Эта функция сейчас работает в бета-режиме. Если вы обнаружите проблемы в её работе, пожалуйста, <a %s>сообщите нам</a>."
837
+
838
+ msgid "We're synchronizing your products. This may take a few minutes. Please do not reload the page."
839
+ msgstr "Товары загружаются. Это может занять несколько минут. Пожалуйста, не перезагружайте страницу."
840
+
841
+ msgid "Products synchronized: %s out of %s"
842
+ msgstr "Загружено товаров: %s из %s"
lib/ecwid_api_v3.php CHANGED
@@ -38,7 +38,7 @@ class Ecwid_Api_V3
38
  update_option(self::TOKEN_OPTION_NAME, $value);
39
  }
40
 
41
- /*
42
  public function get_categories($input_params)
43
  {
44
  $params = array('token');
@@ -85,8 +85,61 @@ class Ecwid_Api_V3
85
 
86
  return $result;
87
  }
88
- */
89
- public function search_products($input_params) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  $params = array('token');
91
 
92
  $passthru = array( 'updatedFrom', 'offset', 'limit', 'sortBy', 'keyword' );
@@ -176,6 +229,34 @@ class Ecwid_Api_V3
176
  return @$result['code'] == 200;
177
  }
178
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  public function create_store()
180
  {
181
  global $current_user;
@@ -245,6 +326,10 @@ class Ecwid_Api_V3
245
  return $result;
246
  }
247
 
 
 
 
 
248
  protected function build_request_url($url, $params)
249
  {
250
  foreach ($params as $key => $param) {
38
  update_option(self::TOKEN_OPTION_NAME, $value);
39
  }
40
 
41
+
42
  public function get_categories($input_params)
43
  {
44
  $params = array('token');
85
 
86
  return $result;
87
  }
88
+
89
+ public function search_products($input_params) {
90
+ $params = array('token');
91
+ $passthru = array( 'updatedFrom', 'offset', 'limit', 'sortBy', 'keyword' );
92
+ foreach ($passthru as $name) {
93
+ if ( array_key_exists( $name, $input_params ) ) {
94
+ $params[$name] = $input_params[$name];
95
+ }
96
+ }
97
+ $result = EcwidPlatform::fetch_url(
98
+ $this->build_request_url(
99
+ $this->_products_api_url,
100
+ $params
101
+ )
102
+ );
103
+ if ($result['code'] != '200') {
104
+ return false;
105
+ }
106
+ $result = json_decode($result['data']);
107
+ return $result;
108
+ }
109
+
110
+ public function get_deleted_products($input_params) {
111
+ $params = array('token');
112
+
113
+ if (array_key_exists('from_date', $input_params)) {
114
+ $params['from_date'] = $input_params['from_date'];
115
+ }
116
+
117
+ if (array_key_exists('offset', $input_params)) {
118
+ $params['offset'] = $input_params['offset'];
119
+ }
120
+
121
+ if (array_key_exists('limit', $input_params)) {
122
+ $params['limit'] = $input_params['limit'];
123
+ }
124
+
125
+ $result = EcwidPlatform::fetch_url(
126
+ $this->build_request_url(
127
+ $this->_products_api_url . '/deleted',
128
+ $params
129
+ )
130
+ );
131
+
132
+ if ($result['code'] != '200') {
133
+ return false;
134
+ }
135
+
136
+ $result = json_decode($result['data']);
137
+
138
+ return $result;
139
+ }
140
+
141
+ public function get_products($input_params)
142
+ {
143
  $params = array('token');
144
 
145
  $passthru = array( 'updatedFrom', 'offset', 'limit', 'sortBy', 'keyword' );
229
  return @$result['code'] == 200;
230
  }
231
 
232
+ public function get_store_update_stats() {
233
+
234
+ $url = $this->_api_url . $this->store_id . '/latest-stats';
235
+
236
+ $params = array(
237
+ 'token' => $this->get_token()
238
+ );
239
+
240
+ $url = $this->build_request_url($url, $params);
241
+ $result = EcwidPlatform::fetch_url($url);
242
+
243
+ return json_decode($result['data']);
244
+ }
245
+
246
+ public function get_store_profile() {
247
+
248
+ $url = $this->_api_url . $this->store_id . '/profile';
249
+
250
+ $params = array(
251
+ 'token' => $this->get_token()
252
+ );
253
+
254
+ $url = $this->build_request_url($url, $params);
255
+ $result = EcwidPlatform::fetch_url($url);
256
+
257
+ return json_decode($result['data']);
258
+ }
259
+
260
  public function create_store()
261
  {
262
  global $current_user;
326
  return $result;
327
  }
328
 
329
+ public static function format_time($time) {
330
+ return strftime('%F %T', $time);
331
+ }
332
+
333
  protected function build_request_url($url, $params)
334
  {
335
  foreach ($params as $key => $param) {
lib/ecwid_platform.php CHANGED
@@ -56,9 +56,14 @@ class EcwidPlatform {
56
  return __('Price', 'ecwid-shopping-cart');
57
  }
58
 
59
- static public function cache_get($name)
60
  {
61
- return get_transient('ecwid_' . $name);
 
 
 
 
 
62
  }
63
 
64
  static public function cache_set($name, $value, $expires_after)
@@ -239,6 +244,11 @@ class EcwidPlatform {
239
  return $transports;
240
  }
241
 
 
 
 
 
 
242
  }
243
 
244
  add_filter('http_api_transports', array('EcwidPlatform', 'http_api_transports'));
56
  return __('Price', 'ecwid-shopping-cart');
57
  }
58
 
59
+ static public function cache_get($name, $default = false)
60
  {
61
+ $result = get_transient('ecwid_' . $name);
62
+ if ($default !== false && $result === false) {
63
+ return $default;
64
+ }
65
+
66
+ return $result;
67
  }
68
 
69
  static public function cache_set($name, $value, $expires_after)
244
  return $transports;
245
  }
246
 
247
+ static public function is_set_time_limit_available() {
248
+ return function_exists('set_time_limit' )
249
+ && strpos( ini_get( 'disable_functions' ), 'set_time_limit' ) == false
250
+ && ! ini_get( 'safe_mode' );
251
+ }
252
  }
253
 
254
  add_filter('http_api_transports', array('EcwidPlatform', 'http_api_transports'));
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: Ecwid
3
  Tags: ecommerce, downloadable products, Facebook ecommerce, online store, paypal, product catalog, shop, shopping cart, store
4
  Requires at least: 3.5
5
  Tested up to: 4.7
6
- Stable tag: 4.8
7
 
8
  Powerful, easy to use ecommerce shopping cart. Bank level PCI DSS Level 1 security. iPhone & Android apps. Superb support. Free plan available.
9
 
@@ -149,6 +149,9 @@ You can use Ecwid’s built-in import tools to copy your store products from any
149
  * [Ecwid eCommerce Forums](https://www.ecwid.com/forums/forumdisplay.php?f=19)
150
 
151
  == Changelog ==
 
 
 
152
  = 4.8 =
153
  - **New "Add product" button in the Wordpress post and page editor.** Now you have a useful and easy tool to place a product from your store on any page or post on your site. Just open any post or page in your Wordpress admin panel, click the "Add product" button in the editor, select the product you want to see on that page and click "Insert" – a product widget will appear on that page after you publish the chnages. The new "Add product" popup allows customizing the appearance of the widget so you can choose whether you want to see the picture along with title, price and quantity selector or just a simple Buy now button. Product widgets that you put on your site are seamlessly integrated with your store and shopping cart — wherever you place a product or buy now button on your site, the customers will be able to add it to the cart and proceed to checkout as if it was a regular store page. We recommend using product widgets and buy now buttons on every page or post where you mention the products or services you sell – this way you will provide an easy and natural way for a customer to know more about the product and buy it from the same page, be it a blog post, an "About" page, a testimonial or any other page on your ecommerce site. Enjoy!
154
 
3
  Tags: ecommerce, downloadable products, Facebook ecommerce, online store, paypal, product catalog, shop, shopping cart, store
4
  Requires at least: 3.5
5
  Tested up to: 4.7
6
+ Stable tag: 4.9
7
 
8
  Powerful, easy to use ecommerce shopping cart. Bank level PCI DSS Level 1 security. iPhone & Android apps. Superb support. Free plan available.
9
 
149
  * [Ecwid eCommerce Forums](https://www.ecwid.com/forums/forumdisplay.php?f=19)
150
 
151
  == Changelog ==
152
+ = 4.9 =
153
+ - **Integration with Wordpress search**. This new feature will make your ecommerce site search find store products among other site pages and posts. So, when your customer searches for something on your site, they will see both site content and store products in the search results and will be able to navigate directly to the product pages from there. Please enable it on the Ecwid/Advanced settings page in your Wordpress backend and do not forget to click "Synchronize products" link. The feature is now in beta stage and we are actively improving it. So if you face any trouble with it, please let us know.
154
+
155
  = 4.8 =
156
  - **New "Add product" button in the Wordpress post and page editor.** Now you have a useful and easy tool to place a product from your store on any page or post on your site. Just open any post or page in your Wordpress admin panel, click the "Add product" button in the editor, select the product you want to see on that page and click "Insert" – a product widget will appear on that page after you publish the chnages. The new "Add product" popup allows customizing the appearance of the widget so you can choose whether you want to see the picture along with title, price and quantity selector or just a simple Buy now button. Product widgets that you put on your site are seamlessly integrated with your store and shopping cart — wherever you place a product or buy now button on your site, the customers will be able to add it to the cart and proceed to checkout as if it was a regular store page. We recommend using product widgets and buy now buttons on every page or post where you mention the products or services you sell – this way you will provide an easy and natural way for a customer to know more about the product and buy it from the same page, be it a blog post, an "About" page, a testimonial or any other page on your ecommerce site. Enjoy!
157
 
templates/advanced-settings.php CHANGED
@@ -100,7 +100,7 @@
100
  checked="checked"
101
  <?php endif; ?>
102
  />
103
- <?php _e('Chameleon skin <sup>beta</sup>', 'ecwid-shopping-cart'); ?>
104
  </label>
105
 
106
  <div class="note">
@@ -171,11 +171,41 @@
171
  </div>
172
  <?php endif; ?>
173
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  </fieldset>
175
 
176
  <fieldset>
177
 
178
- <div class="pure-control-group">
179
  <button type="submit" class="<?php echo ECWID_MAIN_BUTTON_CLASS; ?>">
180
  <?php _e('Save changes', 'ecwid-shopping-cart'); ?>
181
  </button>
100
  checked="checked"
101
  <?php endif; ?>
102
  />
103
+ <?php _e('Chameleon skin', 'ecwid-shopping-cart'); ?>
104
  </label>
105
 
106
  <div class="note">
171
  </div>
172
  <?php endif; ?>
173
 
174
+ <hr />
175
+
176
+ <div class="pure-control-group checkbox">
177
+ <div class="label">
178
+ <label for="<?php echo Ecwid_Products::OPTION_ENABLED; ?>">
179
+
180
+ <input
181
+ id="<?php echo Ecwid_Products::OPTION_ENABLED; ?>"
182
+ name="<?php echo Ecwid_Products::OPTION_ENABLED; ?>"
183
+ type="checkbox"
184
+ <?php if ( Ecwid_Products::is_enabled() ): ?>
185
+ checked="checked"
186
+ <?php endif; ?>
187
+ value="Y"
188
+ />
189
+ <?php _e('Integration with search on your site <sup>beta</sup>', 'ecwid-shopping-cart'); ?>
190
+ </label>
191
+
192
+ <div class="note">
193
+ <?php _e( 'Ecwid stores your products data in a secure cloud storage. The product pages are displayed on the fly when a customer browses your store. So, basically, the products are not stored on the site, that\'s why the site search doesn\'t find product pages while looking through site pages and posts. This option enables a local storage mode: the products will be stored both in the cloud and on your site. The site search results will list product pages as well as regular pages/posts of your site.', 'ecwid-shopping-cart' ); ?>
194
+ </div>
195
+ </div>
196
+ </div>
197
+
198
+ <?php ecwid_sync_do_page(); ?>
199
+
200
+ <div class="note grayed-links">
201
+ <?php echo sprintf(__('Please note this functionality is in beta. So if you run into difficulties or find problems with it, please <a %s>let us know</a>.', 'ecwid-shopping-cart'), ' target="_blank" href="' . __('https://support.ecwid.com/hc/en-us/requests/new', 'ecwid-shopping-cart') . '"'); ?>
202
+ </div>
203
+
204
  </fieldset>
205
 
206
  <fieldset>
207
 
208
+ <div class="pure-control-group" style="margin-top: 30px">
209
  <button type="submit" class="<?php echo ECWID_MAIN_BUTTON_CLASS; ?>">
210
  <?php _e('Save changes', 'ecwid-shopping-cart'); ?>
211
  </button>
templates/product.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+ $content = <<<HTML
3
+ <script>xProductBrowser('defaultProductId=$ecwid_id');</script>
4
+ HTML;
5
+ echo ecwid_wrap_shortcode_content($content, 'product', array());
6
+ ?>
templates/sync.php ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div id="sync-container" class="state-initial"<?php if (!get_option('ecwid_local_base_enabled', false)) echo ' style="display:none"'; ?>>
2
+ <?php
3
+ $prods = new Ecwid_Products();
4
+ $api = new Ecwid_Api_V3(get_ecwid_store_id());
5
+ ?>
6
+
7
+ <script>
8
+ jQuery(document).ready(function() {
9
+
10
+ var sse_available = false;
11
+ var set_time_limit_available = <?php echo EcwidPlatform::is_set_time_limit_available() ? 'true' : 'false'; ?>;
12
+ if (set_time_limit_available && typeof(EventSource) != 'undefined') {
13
+ sse_available = true;
14
+ }
15
+
16
+ if (sse_available) {
17
+ jQuery('#sse_on').html('YES');
18
+ } else {
19
+ jQuery('#sse_on').html('NO');
20
+ jQuery('#sync-container').addClass('no-sse');
21
+ }
22
+
23
+ jQuery('#ecwid_local_base_enabled').click(function() {
24
+ jQuery('#sync-container').css('display', (jQuery(this).is(':checked')) ? '' : 'none');
25
+ });
26
+
27
+ jQuery('#sync-button').click(function() {
28
+ if (sse_available) {
29
+ sync_sse();
30
+ } else {
31
+ sync_by_chunks();
32
+ }
33
+ return false;
34
+ });
35
+
36
+ function sync_sse() {
37
+ jQuery('#sync-container').removeClass('state-initial').addClass('state-in-progress');
38
+
39
+ var source = new EventSource('admin-post.php?action=ecwid_sync_sse');
40
+ source.addEventListener('completed', function(e) {
41
+
42
+ var data = jQuery.parseJSON(e.data);
43
+ jQuery('#sync-container').removeClass('state-in-progress').addClass('state-complete');
44
+ jQuery('#sync-date').text(data.last_update);
45
+ source.close();
46
+ });
47
+
48
+ source.addEventListener('created_product', function(e) {
49
+ increment_progress_counter(1);
50
+ });
51
+
52
+ source.addEventListener('updated_product', function(e) {
53
+ increment_progress_counter(1);
54
+ });
55
+
56
+ source.addEventListener('fetching_products', function(e) {
57
+ var data = jQuery.parseJSON(e.data);
58
+
59
+ jQuery('#current_item').text(
60
+ 'Fetching products... '
61
+ + data.offset + ' - '
62
+ + Math.min(data.offset + data.limit, <?php echo intval($estimation['total_updated']); ?>)
63
+ + ' of <?php echo intval($estimation['total_updated']); ?>');
64
+ });
65
+
66
+ source.addEventListener('fetching_deleted_product_ids', function(e) {
67
+ var data = jQuery.parseJSON(e.data);
68
+
69
+ jQuery('#current_item').text('Fetching deleted products... ' + data.offset + ' - ' + Math.min(data.offset + data.limit, <?php echo intval($estimation['total_deleted']); ?>) + ' of <?php echo intval($estimation['total_deleted']); ?>');
70
+ });
71
+ }
72
+
73
+ var updatedFrom = '<?php echo $estimation['last_update']; ?>';
74
+
75
+ function do_no_sse_sync(mode, offset, limit, time) {
76
+ jQuery.getJSON('admin-post.php?action=ecwid_sync_no_sse&mode=' + mode + '&offset=' + offset + '&limit=' + limit + '&time=' + updatedFrom, {}, process_no_sse_sync);
77
+ }
78
+
79
+ function process_no_sse_sync(data) {
80
+ var mode = 'deleted', offset = 0, limit = 100;
81
+
82
+ var processed_updates = data.updated + data.created + data.deleted_disabled;
83
+ var processed_deletes = data.deleted + data.skipped_deleted;
84
+
85
+ if (processed_updates + processed_deletes == 0) {
86
+ return do_no_sse_over();
87
+ }
88
+
89
+ update_no_sse_stuff(data);
90
+
91
+ if (data.total == data.count + data.offset) {
92
+ if (processed_updates > 0) {
93
+ return do_no_sse_sync('updated', data.offset + limit, limit);
94
+ } else {
95
+ mode = 'updated';
96
+ }
97
+ } else {
98
+ if (processed_updates > 0) {
99
+ mode = 'updated';
100
+ }
101
+ offset = data.offset + data.limit;
102
+ }
103
+ if (mode == 'updated') {
104
+ jQuery('#current_item').text('Updating products...');
105
+ } else {
106
+ jQuery('#current_item').text('Deleting products...');
107
+ }
108
+ do_no_sse_sync(mode, offset, limit, updatedFrom);
109
+ }
110
+
111
+ function update_no_sse_stuff(data) {
112
+ var counters = ['created', 'updated', 'deleted', 'skipped_deleted', 'deleted_disabled'];
113
+ for (var i = 0; i < counters.length; i++) {
114
+ increment_progress_counter(data[counters[i]]);
115
+ }
116
+ }
117
+
118
+ function increment_progress_counter(increment = 1) {
119
+ debugger;
120
+
121
+ if (increment == 0) {
122
+ return;
123
+ }
124
+
125
+ name = 'count_updated';
126
+
127
+ var css = '#' + name;
128
+ var current = jQuery(css).data('count');
129
+ if (!current) {
130
+ current = increment;
131
+ } else {
132
+ current += increment;
133
+ }
134
+ jQuery(css).data('count', current).text(current);
135
+ }
136
+
137
+ function do_no_sse_over() {
138
+ jQuery('#sync-container').removeClass('state-in-progress').addClass('state-complete');
139
+ }
140
+
141
+ jQuery('#sync-button-slow').click(function() {
142
+
143
+ jQuery('#sync-container').removeClass('state-initial').addClass('state-in-progress');
144
+ var mode = 'deleted', offset = 0, limit = 100;
145
+
146
+ jQuery('#current_item').text('Started importing...');
147
+
148
+ do_no_sse_sync(mode, offset, limit);
149
+
150
+ return false;
151
+ });
152
+ jQuery('#sync-button_reset').click(function() {
153
+ location.href='admin-post.php?action=ecwid_sync_reset';
154
+ return false;
155
+ });
156
+ });
157
+ </script>
158
+
159
+ <?php $api = new Ecwid_Api_V3(); if ( !$api->get_token() ): ?>
160
+ <div>
161
+ No token. <a href="<?php echo get_reconnect_link(); ?>">Reconnect</a>
162
+ </div>
163
+ <?php endif; ?>
164
+
165
+ <div class="sync-block" id="sync-button">
166
+ <a id="sync-button"><?php _e('Synchronize products', 'ecwid-shopping-cart'); ?></a>
167
+ <a id="sync-button-slow"><?php _e('Synchronize products', 'ecwid-shopping-cart'); ?></a>
168
+ </div>
169
+ <div class="sync-block" id="updating">
170
+ <div class="sync-icon">
171
+ <?php ecwid_embed_svg('update'); ?>
172
+ </div>
173
+ <div>
174
+ <?php _e('We\'re synchronizing your products. This may take a few minutes. Please do not reload the page.', 'ecwid-shopping-cart'); ?>
175
+ </div>
176
+ </div>
177
+ <div class="sync-block" id="update-progress">
178
+ <?php echo sprintf(__( 'Products synchronized: %s out of %s', 'ecwid-shopping-cart' ),
179
+ '<span id="count_updated">0</span>',
180
+ '<span id="total_updated">' . ($estimation['total_updated'] + $estimation['total_deleted']) . '</span>'
181
+ );
182
+ ?>
183
+ </div>
184
+ <div class="sync-block" id="complete">
185
+ <?php _e( 'Products are successfully synchronized. The product pages are up to date.', 'ecwid-shopping-cart' ); ?>
186
+ </div>
187
+
188
+ <div class="sync-block" id="last-sync-date">
189
+ <?php _e( 'Last update', 'ecwid-shopping-cart' ); ?>:
190
+ <span id="sync-date">
191
+ <?php if ( $estimation['last_update'] == 0 ): ?>
192
+ <?php _e( 'Not synchronized yet', 'ecwid-shopping-cart' ); ?>
193
+ <?php else: ?>
194
+ <?php echo ecwid_format_date( $estimation['last_update'] ); ?>
195
+ <?php endif; ?>
196
+ </span>
197
+ </div>
198
+
199
+ </div>