Version Description
Download this release
Release Info
Developer | Tatvic |
Plugin | Enhanced Ecommerce Google Analytics Plugin for WooCommerce |
Version | 3.0.0 |
Comparing to | |
See all releases |
Code changes from version 2.3.6.1 to 3.0.0
- admin/class-enhanced-ecommerce-google-analytics-admin.php +0 -0
- admin/class-enhanced-ecommerce-google-analytics-settings.php +0 -0
- admin/css/enhanced-ecommerce-google-analytics-admin.css +0 -0
- admin/css/style.css +11 -0
- admin/images/config-success.svg +1 -0
- admin/images/exclaimation.png +0 -0
- admin/images/no-config-success.svg +1 -0
- admin/js/sweetalert.min.js +1 -0
- admin/partials/about-plugin.php +0 -0
- admin/partials/enhanced-ecommerce-google-analytics-admin-display.php +0 -0
- admin/partials/general-fields.php +0 -0
- admin/partials/sidebar.php +0 -0
- css/tvc_admin-page.css +548 -0
- css/tvc_admin-page.min.css +496 -0
- css/tvc_setting-page.css +58 -0
- css/tvc_setting-page.min.css +41 -0
- enhanced-ecommerce-google-analytics.php +0 -0
- google_ads_php.ini +14 -0
- images/ajax-loader.gif +0 -0
- includes/application/class-feed-master.php +676 -0
- includes/application/class-tvc-email.php +68 -0
- includes/application/class-tvc-feed-controller.php +208 -0
- includes/application/class-tvc-feed-processor.php +341 -0
- includes/application/class-tvc-feed-queries.php +243 -0
- includes/application/class-tvc-feed-support.php +301 -0
- includes/application/class-tvc-feed-value-editors.php +240 -0
- includes/application/class-tvc-schedules.php +147 -0
- includes/application/google/class-feed.php +213 -0
- includes/application/google/gmc.txt +23 -0
- includes/application/google/gmc_attrbutes.json +118 -0
- includes/application/google/google.txt +84 -0
- includes/application/google/taxonomy.en-US.txt +5583 -0
- includes/application/google/tvc_google-source.js +292 -0
- includes/application/js/tvc_channel-functions.js +707 -0
- includes/application/js/tvc_channel-functions.min.js +498 -0
- includes/application/js/tvc_feedhandling.js +144 -0
- includes/application/js/tvc_feedhandling.min.js +85 -0
- includes/application/js/tvc_general-functions.js +102 -0
- includes/application/js/tvc_general-functions.min.js +1 -0
- includes/application/js/tvc_logic.js +454 -0
- includes/application/js/tvc_logic.min.js +343 -0
- includes/application/js/tvc_object-attribute-meta.js +66 -0
- includes/application/js/tvc_object-attribute-meta.min.js +1 -0
- includes/application/js/tvc_object-feed.js +849 -0
- includes/application/js/tvc_object-feed.min.js +1 -0
- includes/application/tvc-cron-functions.php +54 -0
- includes/application/tvc-feed-processing-support.php +1583 -0
- includes/application/tvc-feed-processor-functions.php +107 -0
- includes/application/tvc-support-fields.php +118 -0
- includes/class-enhanced-ecommerce-google-analytics.php +0 -0
- includes/class-tvc-register-scripts.php +200 -0
- includes/data/class-tvc-ajax-calls.php +41 -0
- includes/data/class-tvc-ajax-data.php +448 -0
- includes/data/class-tvc-ajax-file.php +1081 -0
- includes/data/class-tvc-backup.php +181 -0
- includes/data/class-tvc-channel-ftp.php +37 -0
- includes/data/class-tvc-channel.php +342 -0
- includes/data/class-tvc-data.php +713 -0
- includes/data/class-tvc-db-management.php +325 -0
- includes/data/class-tvc-feed-crud-handler.php +88 -0
- includes/data/class-tvc-file.php +246 -0
- includes/data/class-tvc-queries.php +970 -0
- includes/data/class-tvc-tab.php +126 -0
- includes/data/class-tvc-taxonomies.php +153 -0
- includes/data/class-tvc-variations.php +85 -0
- includes/data/js/tvc_ajaxdatahandling.js +718 -0
- includes/data/js/tvc_ajaxdatahandling.min.js +364 -0
- includes/data/js/tvc_data.js +105 -0
- includes/data/js/tvc_data.min.js +1 -0
- includes/data/js/tvc_feed-queue-string.js +30 -0
- includes/data/js/tvc_feed-queue-string.min.js +1 -0
- includes/data/js/tvc_metadatahandling.js +596 -0
- includes/data/js/tvc_metadatahandling.min.js +1 -0
- includes/data/tvc-admin-functions.php +91 -0
admin/class-enhanced-ecommerce-google-analytics-admin.php
CHANGED
File without changes
|
admin/class-enhanced-ecommerce-google-analytics-settings.php
CHANGED
File without changes
|
admin/css/enhanced-ecommerce-google-analytics-admin.css
CHANGED
File without changes
|
admin/css/style.css
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
*{
|
2 |
+
box-sizing: border-box;
|
3 |
+
margin:0px;
|
4 |
+
padding:0px;
|
5 |
+
}
|
6 |
+
body{
|
7 |
+
background-image: url('../images/plugin_bk.png') !important;
|
8 |
+
}
|
9 |
+
.swal{
|
10 |
+
background-color:#2c3e50;
|
11 |
+
}
|
admin/images/config-success.svg
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="41" height="41" viewBox="0 0 41 41"><defs><style>.a{fill:#66bb6a;}.b{fill:#fff;stroke:#fff;}</style></defs><g transform="translate(-1199 -247)"><circle class="a" cx="20.5" cy="20.5" r="20.5" transform="translate(1199 247)"/><g transform="translate(1205.572 257.288)"><g transform="translate(0 0)"><path class="b" d="M26.263,68.388a1.333,1.333,0,0,0-1.885,0L8.412,84.355,2.275,78.217A1.333,1.333,0,1,0,.39,80.1l7.08,7.08a1.333,1.333,0,0,0,1.885,0L26.263,70.273A1.333,1.333,0,0,0,26.263,68.388Z" transform="translate(0 -67.997)"/></g></g></g></svg>
|
admin/images/exclaimation.png
ADDED
Binary file
|
admin/images/no-config-success.svg
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
<svg xmlns="http://www.w3.org/2000/svg" width="31.266" height="31.266" viewBox="0 0 31.266 31.266"><defs><style>.a{fill:#25283d;stroke:#25283d;stroke-width:0.5px;}</style></defs><g transform="translate(0.25 0.25)"><g transform="translate(6.41 6.41)"><path class="a" d="M15.9,29.357H12.051a2.081,2.081,0,0,1-1.923-2.307V24.357a4.452,4.452,0,0,0-1.666-3.333A8.861,8.861,0,0,1,5,13.845,9.123,9.123,0,0,1,13.845,5a9.009,9.009,0,0,1,6.41,2.564,9.126,9.126,0,0,1,2.692,6.41A8.621,8.621,0,0,1,19.614,20.9a4.681,4.681,0,0,0-1.795,3.589v2.948A1.972,1.972,0,0,1,15.9,29.357ZM13.973,6.282a7.862,7.862,0,0,0-7.692,7.563A7.535,7.535,0,0,0,9.23,20a5.586,5.586,0,0,1,2.179,4.359v2.692c0,.256,0,1.026.641,1.026H15.9a.606.606,0,0,0,.641-.641V24.485a6.23,6.23,0,0,1,2.307-4.615,7.475,7.475,0,0,0,2.82-5.9,7.663,7.663,0,0,0-2.307-5.512,7.556,7.556,0,0,0-5.384-2.179Z" transform="translate(-5 -5)"/></g><g transform="translate(11.537 25.638)"><path class="a" d="M16.051,21.282H9.641a.641.641,0,1,1,0-1.282h6.41a.641.641,0,1,1,0,1.282Z" transform="translate(-9 -20)"/></g><g transform="translate(14.742)"><path class="a" d="M12.141,3.846A.606.606,0,0,1,11.5,3.2V.641a.641.641,0,0,1,1.282,0V3.2A.606.606,0,0,1,12.141,3.846Z" transform="translate(-11.5)"/></g><g transform="translate(23.267 4.423)"><path class="a" d="M18.855,6.463a.771.771,0,0,1-.513-.128.62.62,0,0,1,0-.9l1.795-1.795a.635.635,0,0,1,.9.9L19.24,6.334A1.291,1.291,0,0,1,18.855,6.463Z" transform="translate(-18.15 -3.45)"/></g><g transform="translate(26.92 14.742)"><path class="a" d="M24.2,12.782H21.641a.641.641,0,0,1,0-1.282H24.2a.641.641,0,1,1,0,1.282Z" transform="translate(-21 -11.5)"/></g><g transform="translate(23.267 23.395)"><path class="a" d="M20.65,21.263a.771.771,0,0,1-.513-.128L18.342,19.34a.635.635,0,0,1,.9-.9l1.795,1.795a.62.62,0,0,1,0,.9c0,.128-.128.128-.385.128Z" transform="translate(-18.15 -18.25)"/></g><g transform="translate(4.294 23.395)"><path class="a" d="M4.055,21.263a.771.771,0,0,1-.513-.128.62.62,0,0,1,0-.9l1.795-1.795a.635.635,0,1,1,.9.9L4.44,21.134a.471.471,0,0,1-.385.128Z" transform="translate(-3.35 -18.25)"/></g><g transform="translate(0 14.742)"><path class="a" d="M3.2,12.782H.641a.641.641,0,0,1,0-1.282H3.2a.641.641,0,0,1,0,1.282Z" transform="translate(0 -11.5)"/></g><g transform="translate(4.294 4.294)"><path class="a" d="M5.85,6.491a.771.771,0,0,1-.513-.128L3.542,4.44a.635.635,0,0,1,.9-.9L6.234,5.337a.62.62,0,0,1,0,.9c-.128.128-.256.256-.385.256Z" transform="translate(-3.35 -3.35)"/></g><g transform="translate(14.742 9.614)"><path class="a" d="M17.269,13.91a.606.606,0,0,1-.641-.641,4.542,4.542,0,0,0-4.487-4.487.641.641,0,0,1,0-1.282,5.745,5.745,0,0,1,5.769,5.769A.606.606,0,0,1,17.269,13.91Z" transform="translate(-11.5 -7.5)"/></g></g></svg>
|
admin/js/sweetalert.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.swal=e():t.swal=e()}(this,function(){return function(t){function e(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,e),r.l=!0,r.exports}var n={};return e.m=t,e.c=n,e.d=function(t,n,o){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:o})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=8)}([function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o="swal-button";e.CLASS_NAMES={MODAL:"swal-modal",OVERLAY:"swal-overlay",SHOW_MODAL:"swal-overlay--show-modal",MODAL_TITLE:"swal-title",MODAL_TEXT:"swal-text",ICON:"swal-icon",ICON_CUSTOM:"swal-icon--custom",CONTENT:"swal-content",FOOTER:"swal-footer",BUTTON_CONTAINER:"swal-button-container",BUTTON:o,CONFIRM_BUTTON:o+"--confirm",CANCEL_BUTTON:o+"--cancel",DANGER_BUTTON:o+"--danger",BUTTON_LOADING:o+"--loading",BUTTON_LOADER:o+"__loader"},e.default=e.CLASS_NAMES},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.getNode=function(t){var e="."+t;return document.querySelector(e)},e.stringToNode=function(t){var e=document.createElement("div");return e.innerHTML=t.trim(),e.firstChild},e.insertAfter=function(t,e){var n=e.nextSibling;e.parentNode.insertBefore(t,n)},e.removeNode=function(t){t.parentElement.removeChild(t)},e.throwErr=function(t){throw t=t.replace(/ +(?= )/g,""),"SweetAlert: "+(t=t.trim())},e.isPlainObject=function(t){if("[object Object]"!==Object.prototype.toString.call(t))return!1;var e=Object.getPrototypeOf(t);return null===e||e===Object.prototype},e.ordinalSuffixOf=function(t){var e=t%10,n=t%100;return 1===e&&11!==n?t+"st":2===e&&12!==n?t+"nd":3===e&&13!==n?t+"rd":t+"th"}},function(t,e,n){"use strict";function o(t){for(var n in t)e.hasOwnProperty(n)||(e[n]=t[n])}Object.defineProperty(e,"__esModule",{value:!0}),o(n(25));var r=n(26);e.overlayMarkup=r.default,o(n(27)),o(n(28)),o(n(29));var i=n(0),a=i.default.MODAL_TITLE,s=i.default.MODAL_TEXT,c=i.default.ICON,l=i.default.FOOTER;e.iconMarkup='\n <div class="'+c+'"></div>',e.titleMarkup='\n <div class="'+a+'"></div>\n',e.textMarkup='\n <div class="'+s+'"></div>',e.footerMarkup='\n <div class="'+l+'"></div>\n'},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1);e.CONFIRM_KEY="confirm",e.CANCEL_KEY="cancel";var r={visible:!0,text:null,value:null,className:"",closeModal:!0},i=Object.assign({},r,{visible:!1,text:"Cancel",value:null}),a=Object.assign({},r,{text:"OK",value:!0});e.defaultButtonList={cancel:i,confirm:a};var s=function(t){switch(t){case e.CONFIRM_KEY:return a;case e.CANCEL_KEY:return i;default:var n=t.charAt(0).toUpperCase()+t.slice(1);return Object.assign({},r,{text:n,value:t})}},c=function(t,e){var n=s(t);return!0===e?Object.assign({},n,{visible:!0}):"string"==typeof e?Object.assign({},n,{visible:!0,text:e}):o.isPlainObject(e)?Object.assign({visible:!0},n,e):Object.assign({},n,{visible:!1})},l=function(t){for(var e={},n=0,o=Object.keys(t);n<o.length;n++){var r=o[n],a=t[r],s=c(r,a);e[r]=s}return e.cancel||(e.cancel=i),e},u=function(t){var n={};switch(t.length){case 1:n[e.CANCEL_KEY]=Object.assign({},i,{visible:!1});break;case 2:n[e.CANCEL_KEY]=c(e.CANCEL_KEY,t[0]),n[e.CONFIRM_KEY]=c(e.CONFIRM_KEY,t[1]);break;default:o.throwErr("Invalid number of 'buttons' in array ("+t.length+").\n If you want more than 2 buttons, you need to use an object!")}return n};e.getButtonListOpts=function(t){var n=e.defaultButtonList;return"string"==typeof t?n[e.CONFIRM_KEY]=c(e.CONFIRM_KEY,t):Array.isArray(t)?n=u(t):o.isPlainObject(t)?n=l(t):!0===t?n=u([!0,!0]):!1===t?n=u([!1,!1]):void 0===t&&(n=e.defaultButtonList),n}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r=n(2),i=n(0),a=i.default.MODAL,s=i.default.OVERLAY,c=n(30),l=n(31),u=n(32),f=n(33);e.injectElIntoModal=function(t){var e=o.getNode(a),n=o.stringToNode(t);return e.appendChild(n),n};var d=function(t){t.className=a,t.textContent=""},p=function(t,e){d(t);var n=e.className;n&&t.classList.add(n)};e.initModalContent=function(t){var e=o.getNode(a);p(e,t),c.default(t.icon),l.initTitle(t.title),l.initText(t.text),f.default(t.content),u.default(t.buttons,t.dangerMode)};var m=function(){var t=o.getNode(s),e=o.stringToNode(r.modalMarkup);t.appendChild(e)};e.default=m},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(3),r={isOpen:!1,promise:null,actions:{},timer:null},i=Object.assign({},r);e.resetState=function(){i=Object.assign({},r)},e.setActionValue=function(t){if("string"==typeof t)return a(o.CONFIRM_KEY,t);for(var e in t)a(e,t[e])};var a=function(t,e){i.actions[t]||(i.actions[t]={}),Object.assign(i.actions[t],{value:e})};e.setActionOptionsFor=function(t,e){var n=(void 0===e?{}:e).closeModal,o=void 0===n||n;Object.assign(i.actions[t],{closeModal:o})},e.default=i},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r=n(3),i=n(0),a=i.default.OVERLAY,s=i.default.SHOW_MODAL,c=i.default.BUTTON,l=i.default.BUTTON_LOADING,u=n(5);e.openModal=function(){o.getNode(a).classList.add(s),u.default.isOpen=!0};var f=function(){o.getNode(a).classList.remove(s),u.default.isOpen=!1};e.onAction=function(t){void 0===t&&(t=r.CANCEL_KEY);var e=u.default.actions[t],n=e.value;if(!1===e.closeModal){var i=c+"--"+t;o.getNode(i).classList.add(l)}else f();u.default.promise.resolve(n)},e.getState=function(){var t=Object.assign({},u.default);return delete t.promise,delete t.timer,t},e.stopLoading=function(){for(var t=document.querySelectorAll("."+c),e=0;e<t.length;e++){t[e].classList.remove(l)}}},function(t,e){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e,n){(function(e){t.exports=e.sweetAlert=n(9)}).call(e,n(7))},function(t,e,n){(function(e){t.exports=e.swal=n(10)}).call(e,n(7))},function(t,e,n){"undefined"!=typeof window&&n(11),n(16);var o=n(23).default;t.exports=o},function(t,e,n){var o=n(12);"string"==typeof o&&(o=[[t.i,o,""]]);var r={insertAt:"top"};r.transform=void 0;n(14)(o,r);o.locals&&(t.exports=o.locals)},function(t,e,n){e=t.exports=n(13)(void 0),e.push([t.i,'.swal-icon--error{border-color:#f27474;-webkit-animation:animateErrorIcon .5s;animation:animateErrorIcon .5s}.swal-icon--error__x-mark{position:relative;display:block;-webkit-animation:animateXMark .5s;animation:animateXMark .5s}.swal-icon--error__line{position:absolute;height:5px;width:47px;background-color:#f27474;display:block;top:37px;border-radius:2px}.swal-icon--error__line--left{-webkit-transform:rotate(45deg);transform:rotate(45deg);left:17px}.swal-icon--error__line--right{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);right:16px}@-webkit-keyframes animateErrorIcon{0%{-webkit-transform:rotateX(100deg);transform:rotateX(100deg);opacity:0}to{-webkit-transform:rotateX(0deg);transform:rotateX(0deg);opacity:1}}@keyframes animateErrorIcon{0%{-webkit-transform:rotateX(100deg);transform:rotateX(100deg);opacity:0}to{-webkit-transform:rotateX(0deg);transform:rotateX(0deg);opacity:1}}@-webkit-keyframes animateXMark{0%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}50%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}80%{-webkit-transform:scale(1.15);transform:scale(1.15);margin-top:-6px}to{-webkit-transform:scale(1);transform:scale(1);margin-top:0;opacity:1}}@keyframes animateXMark{0%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}50%{-webkit-transform:scale(.4);transform:scale(.4);margin-top:26px;opacity:0}80%{-webkit-transform:scale(1.15);transform:scale(1.15);margin-top:-6px}to{-webkit-transform:scale(1);transform:scale(1);margin-top:0;opacity:1}}.swal-icon--warning{border-color:#f8bb86;-webkit-animation:pulseWarning .75s infinite alternate;animation:pulseWarning .75s infinite alternate}.swal-icon--warning__body{width:5px;height:47px;top:10px;border-radius:2px;margin-left:-2px}.swal-icon--warning__body,.swal-icon--warning__dot{position:absolute;left:50%;background-color:#f8bb86}.swal-icon--warning__dot{width:7px;height:7px;border-radius:50%;margin-left:-4px;bottom:-11px}@-webkit-keyframes pulseWarning{0%{border-color:#f8d486}to{border-color:#f8bb86}}@keyframes pulseWarning{0%{border-color:#f8d486}to{border-color:#f8bb86}}.swal-icon--success{border-color:#a5dc86}.swal-icon--success:after,.swal-icon--success:before{content:"";border-radius:50%;position:absolute;width:60px;height:120px;background:#fff;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.swal-icon--success:before{border-radius:120px 0 0 120px;top:-7px;left:-33px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:60px 60px;transform-origin:60px 60px}.swal-icon--success:after{border-radius:0 120px 120px 0;top:-11px;left:30px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:0 60px;transform-origin:0 60px;-webkit-animation:rotatePlaceholder 4.25s ease-in;animation:rotatePlaceholder 4.25s ease-in}.swal-icon--success__ring{width:80px;height:80px;border:4px solid hsla(98,55%,69%,.2);border-radius:50%;box-sizing:content-box;position:absolute;left:-4px;top:-4px;z-index:2}.swal-icon--success__hide-corners{width:5px;height:90px;background-color:#fff;padding:1px;position:absolute;left:28px;top:8px;z-index:1;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.swal-icon--success__line{height:5px;background-color:#a5dc86;display:block;border-radius:2px;position:absolute;z-index:2}.swal-icon--success__line--tip{width:25px;left:14px;top:46px;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-animation:animateSuccessTip .75s;animation:animateSuccessTip .75s}.swal-icon--success__line--long{width:47px;right:8px;top:38px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-animation:animateSuccessLong .75s;animation:animateSuccessLong .75s}@-webkit-keyframes rotatePlaceholder{0%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}5%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}12%{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}to{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}}@keyframes rotatePlaceholder{0%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}5%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}12%{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}to{-webkit-transform:rotate(-405deg);transform:rotate(-405deg)}}@-webkit-keyframes animateSuccessTip{0%{width:0;left:1px;top:19px}54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}to{width:25px;left:14px;top:45px}}@keyframes animateSuccessTip{0%{width:0;left:1px;top:19px}54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}to{width:25px;left:14px;top:45px}}@-webkit-keyframes animateSuccessLong{0%{width:0;right:46px;top:54px}65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}to{width:47px;right:8px;top:38px}}@keyframes animateSuccessLong{0%{width:0;right:46px;top:54px}65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}to{width:47px;right:8px;top:38px}}.swal-icon--info{border-color:#c9dae1}.swal-icon--info:before{width:5px;height:29px;bottom:17px;border-radius:2px;margin-left:-2px}.swal-icon--info:after,.swal-icon--info:before{content:"";position:absolute;left:50%;background-color:#c9dae1}.swal-icon--info:after{width:7px;height:7px;border-radius:50%;margin-left:-3px;top:19px}.swal-icon{width:80px;height:80px;border-width:4px;border-style:solid;border-radius:50%;padding:0;position:relative;box-sizing:content-box;margin:20px auto}.swal-icon:first-child{margin-top:32px}.swal-icon--custom{width:auto;height:auto;max-width:100%;border:none;border-radius:0}.swal-icon img{max-width:100%;max-height:100%}.swal-title{color:rgba(0,0,0,.65);font-weight:600;text-transform:none;position:relative;display:block;padding:13px 16px;font-size:27px;line-height:normal;text-align:center;margin-bottom:0}.swal-title:first-child{margin-top:26px}.swal-title:not(:first-child){padding-bottom:0}.swal-title:not(:last-child){margin-bottom:13px}.swal-text{font-size:16px;position:relative;float:none;line-height:normal;vertical-align:top;text-align:left;display:inline-block;margin:0;padding:0 10px;font-weight:400;color:rgba(0,0,0,.64);max-width:calc(100% - 20px);overflow-wrap:break-word;box-sizing:border-box}.swal-text:first-child{margin-top:45px}.swal-text:last-child{margin-bottom:45px}.swal-footer{text-align:right;padding-top:13px;margin-top:13px;padding:13px 16px;border-radius:inherit;border-top-left-radius:0;border-top-right-radius:0}.swal-button-container{margin:5px;display:inline-block;position:relative}.swal-button{background-color:#7cd1f9;color:#fff;border:none;box-shadow:none;border-radius:5px;font-weight:600;font-size:14px;padding:10px 24px;margin:0;cursor:pointer}.swal-button[not:disabled]:hover{background-color:#78cbf2}.swal-button:active{background-color:#70bce0}.swal-button:focus{outline:none;box-shadow:0 0 0 1px #fff,0 0 0 3px rgba(43,114,165,.29)}.swal-button[disabled]{opacity:.5;cursor:default}.swal-button::-moz-focus-inner{border:0}.swal-button--cancel{color:#555;background-color:#efefef}.swal-button--cancel[not:disabled]:hover{background-color:#e8e8e8}.swal-button--cancel:active{background-color:#d7d7d7}.swal-button--cancel:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px rgba(116,136,150,.29)}.swal-button--danger{background-color:#e64942}.swal-button--danger[not:disabled]:hover{background-color:#df4740}.swal-button--danger:active{background-color:#cf423b}.swal-button--danger:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px rgba(165,43,43,.29)}.swal-content{padding:0 20px;margin-top:20px;font-size:medium}.swal-content:last-child{margin-bottom:20px}.swal-content__input,.swal-content__textarea{-webkit-appearance:none;background-color:#fff;border:none;font-size:14px;display:block;box-sizing:border-box;width:100%;border:1px solid rgba(0,0,0,.14);padding:10px 13px;border-radius:2px;transition:border-color .2s}.swal-content__input:focus,.swal-content__textarea:focus{outline:none;border-color:#6db8ff}.swal-content__textarea{resize:vertical}.swal-button--loading{color:transparent}.swal-button--loading~.swal-button__loader{opacity:1}.swal-button__loader{position:absolute;height:auto;width:43px;z-index:2;left:50%;top:50%;-webkit-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);text-align:center;pointer-events:none;opacity:0}.swal-button__loader div{display:inline-block;float:none;vertical-align:baseline;width:9px;height:9px;padding:0;border:none;margin:2px;opacity:.4;border-radius:7px;background-color:hsla(0,0%,100%,.9);transition:background .2s;-webkit-animation:swal-loading-anim 1s infinite;animation:swal-loading-anim 1s infinite}.swal-button__loader div:nth-child(3n+2){-webkit-animation-delay:.15s;animation-delay:.15s}.swal-button__loader div:nth-child(3n+3){-webkit-animation-delay:.3s;animation-delay:.3s}@-webkit-keyframes swal-loading-anim{0%{opacity:.4}20%{opacity:.4}50%{opacity:1}to{opacity:.4}}@keyframes swal-loading-anim{0%{opacity:.4}20%{opacity:.4}50%{opacity:1}to{opacity:.4}}.swal-overlay{position:fixed;top:0;bottom:0;left:0;right:0;text-align:center;font-size:0;overflow-y:auto;background-color:rgba(0,0,0,.4);z-index:10000;pointer-events:none;opacity:0;transition:opacity .3s}.swal-overlay:before{content:" ";display:inline-block;vertical-align:middle;height:100%}.swal-overlay--show-modal{opacity:1;pointer-events:auto}.swal-overlay--show-modal .swal-modal{opacity:1;pointer-events:auto;box-sizing:border-box;-webkit-animation:showSweetAlert .3s;animation:showSweetAlert .3s;will-change:transform}.swal-modal{width:478px;opacity:0;pointer-events:none;background-color:#fff;text-align:center;border-radius:5px;position:static;margin:20px auto;display:inline-block;vertical-align:middle;-webkit-transform:scale(1);transform:scale(1);-webkit-transform-origin:50% 50%;transform-origin:50% 50%;z-index:10001;transition:opacity .2s,-webkit-transform .3s;transition:transform .3s,opacity .2s;transition:transform .3s,opacity .2s,-webkit-transform .3s}@media (max-width:500px){.swal-modal{width:calc(100% - 20px)}}@-webkit-keyframes showSweetAlert{0%{-webkit-transform:scale(1);transform:scale(1)}1%{-webkit-transform:scale(.5);transform:scale(.5)}45%{-webkit-transform:scale(1.05);transform:scale(1.05)}80%{-webkit-transform:scale(.95);transform:scale(.95)}to{-webkit-transform:scale(1);transform:scale(1)}}@keyframes showSweetAlert{0%{-webkit-transform:scale(1);transform:scale(1)}1%{-webkit-transform:scale(.5);transform:scale(.5)}45%{-webkit-transform:scale(1.05);transform:scale(1.05)}80%{-webkit-transform:scale(.95);transform:scale(.95)}to{-webkit-transform:scale(1);transform:scale(1)}}',""])},function(t,e){function n(t,e){var n=t[1]||"",r=t[3];if(!r)return n;if(e&&"function"==typeof btoa){var i=o(r);return[n].concat(r.sources.map(function(t){return"/*# sourceURL="+r.sourceRoot+t+" */"})).concat([i]).join("\n")}return[n].join("\n")}function o(t){return"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(t))))+" */"}t.exports=function(t){var e=[];return e.toString=function(){return this.map(function(e){var o=n(e,t);return e[2]?"@media "+e[2]+"{"+o+"}":o}).join("")},e.i=function(t,n){"string"==typeof t&&(t=[[null,t,""]]);for(var o={},r=0;r<this.length;r++){var i=this[r][0];"number"==typeof i&&(o[i]=!0)}for(r=0;r<t.length;r++){var a=t[r];"number"==typeof a[0]&&o[a[0]]||(n&&!a[2]?a[2]=n:n&&(a[2]="("+a[2]+") and ("+n+")"),e.push(a))}},e}},function(t,e,n){function o(t,e){for(var n=0;n<t.length;n++){var o=t[n],r=m[o.id];if(r){r.refs++;for(var i=0;i<r.parts.length;i++)r.parts[i](o.parts[i]);for(;i<o.parts.length;i++)r.parts.push(u(o.parts[i],e))}else{for(var a=[],i=0;i<o.parts.length;i++)a.push(u(o.parts[i],e));m[o.id]={id:o.id,refs:1,parts:a}}}}function r(t,e){for(var n=[],o={},r=0;r<t.length;r++){var i=t[r],a=e.base?i[0]+e.base:i[0],s=i[1],c=i[2],l=i[3],u={css:s,media:c,sourceMap:l};o[a]?o[a].parts.push(u):n.push(o[a]={id:a,parts:[u]})}return n}function i(t,e){var n=v(t.insertInto);if(!n)throw new Error("Couldn't find a style target. This probably means that the value for the 'insertInto' parameter is invalid.");var o=w[w.length-1];if("top"===t.insertAt)o?o.nextSibling?n.insertBefore(e,o.nextSibling):n.appendChild(e):n.insertBefore(e,n.firstChild),w.push(e);else{if("bottom"!==t.insertAt)throw new Error("Invalid value for parameter 'insertAt'. Must be 'top' or 'bottom'.");n.appendChild(e)}}function a(t){if(null===t.parentNode)return!1;t.parentNode.removeChild(t);var e=w.indexOf(t);e>=0&&w.splice(e,1)}function s(t){var e=document.createElement("style");return t.attrs.type="text/css",l(e,t.attrs),i(t,e),e}function c(t){var e=document.createElement("link");return t.attrs.type="text/css",t.attrs.rel="stylesheet",l(e,t.attrs),i(t,e),e}function l(t,e){Object.keys(e).forEach(function(n){t.setAttribute(n,e[n])})}function u(t,e){var n,o,r,i;if(e.transform&&t.css){if(!(i=e.transform(t.css)))return function(){};t.css=i}if(e.singleton){var l=h++;n=g||(g=s(e)),o=f.bind(null,n,l,!1),r=f.bind(null,n,l,!0)}else t.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=c(e),o=p.bind(null,n,e),r=function(){a(n),n.href&&URL.revokeObjectURL(n.href)}):(n=s(e),o=d.bind(null,n),r=function(){a(n)});return o(t),function(e){if(e){if(e.css===t.css&&e.media===t.media&&e.sourceMap===t.sourceMap)return;o(t=e)}else r()}}function f(t,e,n,o){var r=n?"":o.css;if(t.styleSheet)t.styleSheet.cssText=x(e,r);else{var i=document.createTextNode(r),a=t.childNodes;a[e]&&t.removeChild(a[e]),a.length?t.insertBefore(i,a[e]):t.appendChild(i)}}function d(t,e){var n=e.css,o=e.media;if(o&&t.setAttribute("media",o),t.styleSheet)t.styleSheet.cssText=n;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(n))}}function p(t,e,n){var o=n.css,r=n.sourceMap,i=void 0===e.convertToAbsoluteUrls&&r;(e.convertToAbsoluteUrls||i)&&(o=y(o)),r&&(o+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(r))))+" */");var a=new Blob([o],{type:"text/css"}),s=t.href;t.href=URL.createObjectURL(a),s&&URL.revokeObjectURL(s)}var m={},b=function(t){var e;return function(){return void 0===e&&(e=t.apply(this,arguments)),e}}(function(){return window&&document&&document.all&&!window.atob}),v=function(t){var e={};return function(n){return void 0===e[n]&&(e[n]=t.call(this,n)),e[n]}}(function(t){return document.querySelector(t)}),g=null,h=0,w=[],y=n(15);t.exports=function(t,e){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");e=e||{},e.attrs="object"==typeof e.attrs?e.attrs:{},e.singleton||(e.singleton=b()),e.insertInto||(e.insertInto="head"),e.insertAt||(e.insertAt="bottom");var n=r(t,e);return o(n,e),function(t){for(var i=[],a=0;a<n.length;a++){var s=n[a],c=m[s.id];c.refs--,i.push(c)}if(t){o(r(t,e),e)}for(var a=0;a<i.length;a++){var c=i[a];if(0===c.refs){for(var l=0;l<c.parts.length;l++)c.parts[l]();delete m[c.id]}}}};var x=function(){var t=[];return function(e,n){return t[e]=n,t.filter(Boolean).join("\n")}}()},function(t,e){t.exports=function(t){var e="undefined"!=typeof window&&window.location;if(!e)throw new Error("fixUrls requires window.location");if(!t||"string"!=typeof t)return t;var n=e.protocol+"//"+e.host,o=n+e.pathname.replace(/\/[^\/]*$/,"/");return t.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi,function(t,e){var r=e.trim().replace(/^"(.*)"$/,function(t,e){return e}).replace(/^'(.*)'$/,function(t,e){return e});if(/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/)/i.test(r))return t;var i;return i=0===r.indexOf("//")?r:0===r.indexOf("/")?n+r:o+r.replace(/^\.\//,""),"url("+JSON.stringify(i)+")"})}},function(t,e,n){var o=n(17);"undefined"==typeof window||window.Promise||(window.Promise=o),n(21),String.prototype.includes||(String.prototype.includes=function(t,e){"use strict";return"number"!=typeof e&&(e=0),!(e+t.length>this.length)&&-1!==this.indexOf(t,e)}),Array.prototype.includes||Object.defineProperty(Array.prototype,"includes",{value:function(t,e){if(null==this)throw new TypeError('"this" is null or not defined');var n=Object(this),o=n.length>>>0;if(0===o)return!1;for(var r=0|e,i=Math.max(r>=0?r:o-Math.abs(r),0);i<o;){if(function(t,e){return t===e||"number"==typeof t&&"number"==typeof e&&isNaN(t)&&isNaN(e)}(n[i],t))return!0;i++}return!1}}),"undefined"!=typeof window&&function(t){t.forEach(function(t){t.hasOwnProperty("remove")||Object.defineProperty(t,"remove",{configurable:!0,enumerable:!0,writable:!0,value:function(){this.parentNode.removeChild(this)}})})}([Element.prototype,CharacterData.prototype,DocumentType.prototype])},function(t,e,n){(function(e){!function(n){function o(){}function r(t,e){return function(){t.apply(e,arguments)}}function i(t){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof t)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],f(t,this)}function a(t,e){for(;3===t._state;)t=t._value;if(0===t._state)return void t._deferreds.push(e);t._handled=!0,i._immediateFn(function(){var n=1===t._state?e.onFulfilled:e.onRejected;if(null===n)return void(1===t._state?s:c)(e.promise,t._value);var o;try{o=n(t._value)}catch(t){return void c(e.promise,t)}s(e.promise,o)})}function s(t,e){try{if(e===t)throw new TypeError("A promise cannot be resolved with itself.");if(e&&("object"==typeof e||"function"==typeof e)){var n=e.then;if(e instanceof i)return t._state=3,t._value=e,void l(t);if("function"==typeof n)return void f(r(n,e),t)}t._state=1,t._value=e,l(t)}catch(e){c(t,e)}}function c(t,e){t._state=2,t._value=e,l(t)}function l(t){2===t._state&&0===t._deferreds.length&&i._immediateFn(function(){t._handled||i._unhandledRejectionFn(t._value)});for(var e=0,n=t._deferreds.length;e<n;e++)a(t,t._deferreds[e]);t._deferreds=null}function u(t,e,n){this.onFulfilled="function"==typeof t?t:null,this.onRejected="function"==typeof e?e:null,this.promise=n}function f(t,e){var n=!1;try{t(function(t){n||(n=!0,s(e,t))},function(t){n||(n=!0,c(e,t))})}catch(t){if(n)return;n=!0,c(e,t)}}var d=setTimeout;i.prototype.catch=function(t){return this.then(null,t)},i.prototype.then=function(t,e){var n=new this.constructor(o);return a(this,new u(t,e,n)),n},i.all=function(t){var e=Array.prototype.slice.call(t);return new i(function(t,n){function o(i,a){try{if(a&&("object"==typeof a||"function"==typeof a)){var s=a.then;if("function"==typeof s)return void s.call(a,function(t){o(i,t)},n)}e[i]=a,0==--r&&t(e)}catch(t){n(t)}}if(0===e.length)return t([]);for(var r=e.length,i=0;i<e.length;i++)o(i,e[i])})},i.resolve=function(t){return t&&"object"==typeof t&&t.constructor===i?t:new i(function(e){e(t)})},i.reject=function(t){return new i(function(e,n){n(t)})},i.race=function(t){return new i(function(e,n){for(var o=0,r=t.length;o<r;o++)t[o].then(e,n)})},i._immediateFn="function"==typeof e&&function(t){e(t)}||function(t){d(t,0)},i._unhandledRejectionFn=function(t){"undefined"!=typeof console&&console&&console.warn("Possible Unhandled Promise Rejection:",t)},i._setImmediateFn=function(t){i._immediateFn=t},i._setUnhandledRejectionFn=function(t){i._unhandledRejectionFn=t},void 0!==t&&t.exports?t.exports=i:n.Promise||(n.Promise=i)}(this)}).call(e,n(18).setImmediate)},function(t,e,n){function o(t,e){this._id=t,this._clearFn=e}var r=Function.prototype.apply;e.setTimeout=function(){return new o(r.call(setTimeout,window,arguments),clearTimeout)},e.setInterval=function(){return new o(r.call(setInterval,window,arguments),clearInterval)},e.clearTimeout=e.clearInterval=function(t){t&&t.close()},o.prototype.unref=o.prototype.ref=function(){},o.prototype.close=function(){this._clearFn.call(window,this._id)},e.enroll=function(t,e){clearTimeout(t._idleTimeoutId),t._idleTimeout=e},e.unenroll=function(t){clearTimeout(t._idleTimeoutId),t._idleTimeout=-1},e._unrefActive=e.active=function(t){clearTimeout(t._idleTimeoutId);var e=t._idleTimeout;e>=0&&(t._idleTimeoutId=setTimeout(function(){t._onTimeout&&t._onTimeout()},e))},n(19),e.setImmediate=setImmediate,e.clearImmediate=clearImmediate},function(t,e,n){(function(t,e){!function(t,n){"use strict";function o(t){"function"!=typeof t&&(t=new Function(""+t));for(var e=new Array(arguments.length-1),n=0;n<e.length;n++)e[n]=arguments[n+1];var o={callback:t,args:e};return l[c]=o,s(c),c++}function r(t){delete l[t]}function i(t){var e=t.callback,o=t.args;switch(o.length){case 0:e();break;case 1:e(o[0]);break;case 2:e(o[0],o[1]);break;case 3:e(o[0],o[1],o[2]);break;default:e.apply(n,o)}}function a(t){if(u)setTimeout(a,0,t);else{var e=l[t];if(e){u=!0;try{i(e)}finally{r(t),u=!1}}}}if(!t.setImmediate){var s,c=1,l={},u=!1,f=t.document,d=Object.getPrototypeOf&&Object.getPrototypeOf(t);d=d&&d.setTimeout?d:t,"[object process]"==={}.toString.call(t.process)?function(){s=function(t){e.nextTick(function(){a(t)})}}():function(){if(t.postMessage&&!t.importScripts){var e=!0,n=t.onmessage;return t.onmessage=function(){e=!1},t.postMessage("","*"),t.onmessage=n,e}}()?function(){var e="setImmediate$"+Math.random()+"$",n=function(n){n.source===t&&"string"==typeof n.data&&0===n.data.indexOf(e)&&a(+n.data.slice(e.length))};t.addEventListener?t.addEventListener("message",n,!1):t.attachEvent("onmessage",n),s=function(n){t.postMessage(e+n,"*")}}():t.MessageChannel?function(){var t=new MessageChannel;t.port1.onmessage=function(t){a(t.data)},s=function(e){t.port2.postMessage(e)}}():f&&"onreadystatechange"in f.createElement("script")?function(){var t=f.documentElement;s=function(e){var n=f.createElement("script");n.onreadystatechange=function(){a(e),n.onreadystatechange=null,t.removeChild(n),n=null},t.appendChild(n)}}():function(){s=function(t){setTimeout(a,0,t)}}(),d.setImmediate=o,d.clearImmediate=r}}("undefined"==typeof self?void 0===t?this:t:self)}).call(e,n(7),n(20))},function(t,e){function n(){throw new Error("setTimeout has not been defined")}function o(){throw new Error("clearTimeout has not been defined")}function r(t){if(u===setTimeout)return setTimeout(t,0);if((u===n||!u)&&setTimeout)return u=setTimeout,setTimeout(t,0);try{return u(t,0)}catch(e){try{return u.call(null,t,0)}catch(e){return u.call(this,t,0)}}}function i(t){if(f===clearTimeout)return clearTimeout(t);if((f===o||!f)&&clearTimeout)return f=clearTimeout,clearTimeout(t);try{return f(t)}catch(e){try{return f.call(null,t)}catch(e){return f.call(this,t)}}}function a(){b&&p&&(b=!1,p.length?m=p.concat(m):v=-1,m.length&&s())}function s(){if(!b){var t=r(a);b=!0;for(var e=m.length;e;){for(p=m,m=[];++v<e;)p&&p[v].run();v=-1,e=m.length}p=null,b=!1,i(t)}}function c(t,e){this.fun=t,this.array=e}function l(){}var u,f,d=t.exports={};!function(){try{u="function"==typeof setTimeout?setTimeout:n}catch(t){u=n}try{f="function"==typeof clearTimeout?clearTimeout:o}catch(t){f=o}}();var p,m=[],b=!1,v=-1;d.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)e[n-1]=arguments[n];m.push(new c(t,e)),1!==m.length||b||r(s)},c.prototype.run=function(){this.fun.apply(null,this.array)},d.title="browser",d.browser=!0,d.env={},d.argv=[],d.version="",d.versions={},d.on=l,d.addListener=l,d.once=l,d.off=l,d.removeListener=l,d.removeAllListeners=l,d.emit=l,d.prependListener=l,d.prependOnceListener=l,d.listeners=function(t){return[]},d.binding=function(t){throw new Error("process.binding is not supported")},d.cwd=function(){return"/"},d.chdir=function(t){throw new Error("process.chdir is not supported")},d.umask=function(){return 0}},function(t,e,n){"use strict";n(22).polyfill()},function(t,e,n){"use strict";function o(t,e){if(void 0===t||null===t)throw new TypeError("Cannot convert first argument to object");for(var n=Object(t),o=1;o<arguments.length;o++){var r=arguments[o];if(void 0!==r&&null!==r)for(var i=Object.keys(Object(r)),a=0,s=i.length;a<s;a++){var c=i[a],l=Object.getOwnPropertyDescriptor(r,c);void 0!==l&&l.enumerable&&(n[c]=r[c])}}return n}function r(){Object.assign||Object.defineProperty(Object,"assign",{enumerable:!1,configurable:!0,writable:!0,value:o})}t.exports={assign:o,polyfill:r}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(24),r=n(6),i=n(5),a=n(36),s=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];if("undefined"!=typeof window){var n=a.getOpts.apply(void 0,t);return new Promise(function(t,e){i.default.promise={resolve:t,reject:e},o.default(n),setTimeout(function(){r.openModal()})})}};s.close=r.onAction,s.getState=r.getState,s.setActionValue=i.setActionValue,s.stopLoading=r.stopLoading,s.setDefaults=a.setDefaults,e.default=s},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r=n(0),i=r.default.MODAL,a=n(4),s=n(34),c=n(35),l=n(1);e.init=function(t){o.getNode(i)||(document.body||l.throwErr("You can only use SweetAlert AFTER the DOM has loaded!"),s.default(),a.default()),a.initModalContent(t),c.default(t)},e.default=e.init},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),r=o.default.MODAL;e.modalMarkup='\n <div class="'+r+'" role="dialog" aria-modal="true"></div>',e.default=e.modalMarkup},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),r=o.default.OVERLAY,i='<div \n class="'+r+'"\n tabIndex="-1">\n </div>';e.default=i},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),r=o.default.ICON;e.errorIconMarkup=function(){var t=r+"--error",e=t+"__line";return'\n <div class="'+t+'__x-mark">\n <span class="'+e+" "+e+'--left"></span>\n <span class="'+e+" "+e+'--right"></span>\n </div>\n '},e.warningIconMarkup=function(){var t=r+"--warning";return'\n <span class="'+t+'__body">\n <span class="'+t+'__dot"></span>\n </span>\n '},e.successIconMarkup=function(){var t=r+"--success";return'\n <span class="'+t+"__line "+t+'__line--long"></span>\n <span class="'+t+"__line "+t+'__line--tip"></span>\n\n <div class="'+t+'__ring"></div>\n <div class="'+t+'__hide-corners"></div>\n '}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),r=o.default.CONTENT;e.contentMarkup='\n <div class="'+r+'">\n\n </div>\n'},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(0),r=o.default.BUTTON_CONTAINER,i=o.default.BUTTON,a=o.default.BUTTON_LOADER;e.buttonMarkup='\n <div class="'+r+'">\n\n <button\n class="'+i+'"\n ></button>\n\n <div class="'+a+'">\n <div></div>\n <div></div>\n <div></div>\n </div>\n\n </div>\n'},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(4),r=n(2),i=n(0),a=i.default.ICON,s=i.default.ICON_CUSTOM,c=["error","warning","success","info"],l={error:r.errorIconMarkup(),warning:r.warningIconMarkup(),success:r.successIconMarkup()},u=function(t,e){var n=a+"--"+t;e.classList.add(n);var o=l[t];o&&(e.innerHTML=o)},f=function(t,e){e.classList.add(s);var n=document.createElement("img");n.src=t,e.appendChild(n)},d=function(t){if(t){var e=o.injectElIntoModal(r.iconMarkup);c.includes(t)?u(t,e):f(t,e)}};e.default=d},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(2),r=n(4),i=function(t){navigator.userAgent.includes("AppleWebKit")&&(t.style.display="none",t.offsetHeight,t.style.display="")};e.initTitle=function(t){if(t){var e=r.injectElIntoModal(o.titleMarkup);e.textContent=t,i(e)}},e.initText=function(t){if(t){var e=document.createDocumentFragment();t.split("\n").forEach(function(t,n,o){e.appendChild(document.createTextNode(t)),n<o.length-1&&e.appendChild(document.createElement("br"))});var n=r.injectElIntoModal(o.textMarkup);n.appendChild(e),i(n)}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r=n(4),i=n(0),a=i.default.BUTTON,s=i.default.DANGER_BUTTON,c=n(3),l=n(2),u=n(6),f=n(5),d=function(t,e,n){var r=e.text,i=e.value,d=e.className,p=e.closeModal,m=o.stringToNode(l.buttonMarkup),b=m.querySelector("."+a),v=a+"--"+t;if(b.classList.add(v),d){(Array.isArray(d)?d:d.split(" ")).filter(function(t){return t.length>0}).forEach(function(t){b.classList.add(t)})}n&&t===c.CONFIRM_KEY&&b.classList.add(s),b.textContent=r;var g={};return g[t]=i,f.setActionValue(g),f.setActionOptionsFor(t,{closeModal:p}),b.addEventListener("click",function(){return u.onAction(t)}),m},p=function(t,e){var n=r.injectElIntoModal(l.footerMarkup);for(var o in t){var i=t[o],a=d(o,i,e);i.visible&&n.appendChild(a)}0===n.children.length&&n.remove()};e.default=p},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(3),r=n(4),i=n(2),a=n(5),s=n(6),c=n(0),l=c.default.CONTENT,u=function(t){t.addEventListener("input",function(t){var e=t.target,n=e.value;a.setActionValue(n)}),t.addEventListener("keyup",function(t){if("Enter"===t.key)return s.onAction(o.CONFIRM_KEY)}),setTimeout(function(){t.focus(),a.setActionValue("")},0)},f=function(t,e,n){var o=document.createElement(e),r=l+"__"+e;o.classList.add(r);for(var i in n){var a=n[i];o[i]=a}"input"===e&&u(o),t.appendChild(o)},d=function(t){if(t){var e=r.injectElIntoModal(i.contentMarkup),n=t.element,o=t.attributes;"string"==typeof n?f(e,n,o):e.appendChild(n)}};e.default=d},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r=n(2),i=function(){var t=o.stringToNode(r.overlayMarkup);document.body.appendChild(t)};e.default=i},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(5),r=n(6),i=n(1),a=n(3),s=n(0),c=s.default.MODAL,l=s.default.BUTTON,u=s.default.OVERLAY,f=function(t){t.preventDefault(),v()},d=function(t){t.preventDefault(),g()},p=function(t){if(o.default.isOpen)switch(t.key){case"Escape":return r.onAction(a.CANCEL_KEY)}},m=function(t){if(o.default.isOpen)switch(t.key){case"Tab":return f(t)}},b=function(t){if(o.default.isOpen)return"Tab"===t.key&&t.shiftKey?d(t):void 0},v=function(){var t=i.getNode(l);t&&(t.tabIndex=0,t.focus())},g=function(){var t=i.getNode(c),e=t.querySelectorAll("."+l),n=e.length-1,o=e[n];o&&o.focus()},h=function(t){t[t.length-1].addEventListener("keydown",m)},w=function(t){t[0].addEventListener("keydown",b)},y=function(){var t=i.getNode(c),e=t.querySelectorAll("."+l);e.length&&(h(e),w(e))},x=function(t){if(i.getNode(u)===t.target)return r.onAction(a.CANCEL_KEY)},_=function(t){var e=i.getNode(u);e.removeEventListener("click",x),t&&e.addEventListener("click",x)},k=function(t){o.default.timer&&clearTimeout(o.default.timer),t&&(o.default.timer=window.setTimeout(function(){return r.onAction(a.CANCEL_KEY)},t))},O=function(t){t.closeOnEsc?document.addEventListener("keyup",p):document.removeEventListener("keyup",p),t.dangerMode?v():g(),y(),_(t.closeOnClickOutside),k(t.timer)};e.default=O},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r=n(3),i=n(37),a=n(38),s={title:null,text:null,icon:null,buttons:r.defaultButtonList,content:null,className:null,closeOnClickOutside:!0,closeOnEsc:!0,dangerMode:!1,timer:null},c=Object.assign({},s);e.setDefaults=function(t){c=Object.assign({},s,t)};var l=function(t){var e=t&&t.button,n=t&&t.buttons;return void 0!==e&&void 0!==n&&o.throwErr("Cannot set both 'button' and 'buttons' options!"),void 0!==e?{confirm:e}:n},u=function(t){return o.ordinalSuffixOf(t+1)},f=function(t,e){o.throwErr(u(e)+" argument ('"+t+"') is invalid")},d=function(t,e){var n=t+1,r=e[n];o.isPlainObject(r)||void 0===r||o.throwErr("Expected "+u(n)+" argument ('"+r+"') to be a plain object")},p=function(t,e){var n=t+1,r=e[n];void 0!==r&&o.throwErr("Unexpected "+u(n)+" argument ("+r+")")},m=function(t,e,n,r){var i=typeof e,a="string"===i,s=e instanceof Element;if(a){if(0===n)return{text:e};if(1===n)return{text:e,title:r[0]};if(2===n)return d(n,r),{icon:e};f(e,n)}else{if(s&&0===n)return d(n,r),{content:e};if(o.isPlainObject(e))return p(n,r),e;f(e,n)}};e.getOpts=function(){for(var t=[],e=0;e<arguments.length;e++)t[e]=arguments[e];var n={};t.forEach(function(e,o){var r=m(0,e,o,t);Object.assign(n,r)});var o=l(n);n.buttons=r.getButtonListOpts(o),delete n.button,n.content=i.getContentOpts(n.content);var u=Object.assign({},s,c,n);return Object.keys(u).forEach(function(t){a.DEPRECATED_OPTS[t]&&a.logDeprecation(t)}),u}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var o=n(1),r={element:"input",attributes:{placeholder:""}};e.getContentOpts=function(t){var e={};return o.isPlainObject(t)?Object.assign(e,t):t instanceof Element?{element:t}:"input"===t?r:null}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.logDeprecation=function(t){var n=e.DEPRECATED_OPTS[t],o=n.onlyRename,r=n.replacement,i=n.subOption,a=n.link,s=o?"renamed":"deprecated",c='SweetAlert warning: "'+t+'" option has been '+s+".";if(r){c+=" Please use"+(i?' "'+i+'" in ':" ")+'"'+r+'" instead.'}var l="https://sweetalert.js.org";c+=a?" More details: "+l+a:" More details: "+l+"/guides/#upgrading-from-1x",console.warn(c)},e.DEPRECATED_OPTS={type:{replacement:"icon",link:"/docs/#icon"},imageUrl:{replacement:"icon",link:"/docs/#icon"},customClass:{replacement:"className",onlyRename:!0,link:"/docs/#classname"},imageSize:{},showCancelButton:{replacement:"buttons",link:"/docs/#buttons"},showConfirmButton:{replacement:"button",link:"/docs/#button"},confirmButtonText:{replacement:"button",link:"/docs/#button"},confirmButtonColor:{},cancelButtonText:{replacement:"buttons",link:"/docs/#buttons"},closeOnConfirm:{replacement:"button",subOption:"closeModal",link:"/docs/#button"},closeOnCancel:{replacement:"buttons",subOption:"closeModal",link:"/docs/#buttons"},showLoaderOnConfirm:{replacement:"buttons"},animation:{},inputType:{replacement:"content",link:"/docs/#content"},inputValue:{replacement:"content",link:"/docs/#content"},inputPlaceholder:{replacement:"content",link:"/docs/#content"},html:{replacement:"content",link:"/docs/#content"},allowEscapeKey:{replacement:"closeOnEsc",onlyRename:!0,link:"/docs/#closeonesc"},allowClickOutside:{replacement:"closeOnClickOutside",onlyRename:!0,link:"/docs/#closeonclickoutside"}}}])});
|
admin/partials/about-plugin.php
CHANGED
File without changes
|
admin/partials/enhanced-ecommerce-google-analytics-admin-display.php
CHANGED
File without changes
|
admin/partials/general-fields.php
CHANGED
File without changes
|
admin/partials/sidebar.php
CHANGED
File without changes
|
css/tvc_admin-page.css
ADDED
@@ -0,0 +1,548 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*
|
2 |
+
To change this license header, choose License Headers in Project Properties.
|
3 |
+
To change this template file, choose Tools | Templates
|
4 |
+
and open the template in the editor.
|
5 |
+
*/
|
6 |
+
|
7 |
+
#feed-spinner {
|
8 |
+
/*height: 200px;*/ /*height of the spinner gif +2px to fix IE8 issue */
|
9 |
+
left: 50%;
|
10 |
+
margin-left: -25px; /* half width of the spinner gif */
|
11 |
+
margin-top: -25px; /* half height of the spinner gif */
|
12 |
+
overflow: auto;
|
13 |
+
position: fixed;
|
14 |
+
text-align: center;
|
15 |
+
top: 40%;
|
16 |
+
/*width: 200px;*/ /* width of the spinner gif */
|
17 |
+
z-index: 1234;
|
18 |
+
}
|
19 |
+
div.field-table-row-wrapper:nth-child(2n) {
|
20 |
+
background-color: #f5f5f5;
|
21 |
+
}
|
22 |
+
|
23 |
+
#footer-left{
|
24 |
+
display: none;
|
25 |
+
}
|
26 |
+
|
27 |
+
div.field-table-row-wrapper {
|
28 |
+
display: block;
|
29 |
+
padding-bottom: 5px;
|
30 |
+
}
|
31 |
+
|
32 |
+
div.filter-wrapper {
|
33 |
+
margin-top: 5px;
|
34 |
+
}
|
35 |
+
|
36 |
+
aside.action-btn {
|
37 |
+
margin-left: 8px;
|
38 |
+
}
|
39 |
+
|
40 |
+
.small-text {
|
41 |
+
width: 15px;
|
42 |
+
}
|
43 |
+
|
44 |
+
.field-level {
|
45 |
+
background: #e5e5e5;
|
46 |
+
clear: both;
|
47 |
+
font-size: 15px;
|
48 |
+
line-height: 30px;
|
49 |
+
padding-left: 5px;
|
50 |
+
}
|
51 |
+
|
52 |
+
.value-options-condition-selector {
|
53 |
+
margin-left: 400px;
|
54 |
+
}
|
55 |
+
|
56 |
+
.value-options-query-selector {
|
57 |
+
margin-bottom: 15px;
|
58 |
+
margin-left: 37%;
|
59 |
+
width: 65%
|
60 |
+
}
|
61 |
+
|
62 |
+
select.tvc-main-input-selector {
|
63 |
+
height: 33px;
|
64 |
+
max-width: 35rem;
|
65 |
+
}
|
66 |
+
|
67 |
+
select.select-value-options {
|
68 |
+
height: 27px;
|
69 |
+
vertical-align: initial;
|
70 |
+
}
|
71 |
+
|
72 |
+
select.align-left {
|
73 |
+
float: left;
|
74 |
+
}
|
75 |
+
|
76 |
+
.condition-and-value-selector {
|
77 |
+
margin-left: 5px;
|
78 |
+
}
|
79 |
+
|
80 |
+
div.condition-wrapper {
|
81 |
+
float: left;
|
82 |
+
line-height: 26px;
|
83 |
+
margin-bottom: 15px;
|
84 |
+
width: 100%;
|
85 |
+
}
|
86 |
+
|
87 |
+
div.source-data-column {
|
88 |
+
}
|
89 |
+
|
90 |
+
div.change-source-value-wrapper {
|
91 |
+
background-color: #e2e2e2;
|
92 |
+
float: left;
|
93 |
+
margin-left: 16%;
|
94 |
+
padding: 15px;
|
95 |
+
width: 81%;
|
96 |
+
}
|
97 |
+
|
98 |
+
th#tvc-main-feed-input-label {
|
99 |
+
text-align: left;
|
100 |
+
width: 32%;
|
101 |
+
}
|
102 |
+
|
103 |
+
th#tvc-main-feed-input-label label {
|
104 |
+
display: inline-block;
|
105 |
+
}
|
106 |
+
|
107 |
+
div.edit-value-control {
|
108 |
+
float: right;
|
109 |
+
margin: -50px 10px;
|
110 |
+
}
|
111 |
+
|
112 |
+
div.add-to-feed-column {
|
113 |
+
margin-top: 4px;
|
114 |
+
}
|
115 |
+
|
116 |
+
div.tvc-header-wrapper {
|
117 |
+
padding-bottom: 10px;
|
118 |
+
}
|
119 |
+
|
120 |
+
div.tvc-field-header-wrapper {
|
121 |
+
background-color: white;
|
122 |
+
height: 30px;
|
123 |
+
margin-bottom: 10px;
|
124 |
+
}
|
125 |
+
|
126 |
+
div.field-header {
|
127 |
+
float: left;
|
128 |
+
margin-bottom: 8px;
|
129 |
+
padding: 5px;
|
130 |
+
}
|
131 |
+
|
132 |
+
.col10w {
|
133 |
+
width: 10%;
|
134 |
+
}
|
135 |
+
|
136 |
+
.col30w {
|
137 |
+
width: 30%;
|
138 |
+
}
|
139 |
+
|
140 |
+
.col20w {
|
141 |
+
width: 16%;
|
142 |
+
}
|
143 |
+
|
144 |
+
.col40w {
|
145 |
+
width: 40%;
|
146 |
+
}
|
147 |
+
|
148 |
+
.col55w {
|
149 |
+
width: 55%;
|
150 |
+
}
|
151 |
+
|
152 |
+
.col80w {
|
153 |
+
width: 82%;
|
154 |
+
}
|
155 |
+
|
156 |
+
.condition-selector {
|
157 |
+
width: 55%;
|
158 |
+
}
|
159 |
+
|
160 |
+
div#category-mapping-header {
|
161 |
+
left: 15px;
|
162 |
+
position: relative;
|
163 |
+
}
|
164 |
+
|
165 |
+
div.source-selector {
|
166 |
+
margin-right: 6%;
|
167 |
+
}
|
168 |
+
|
169 |
+
div.tvc-feedback {
|
170 |
+
background-color: #fff;
|
171 |
+
border: 1px solid #e5e5e5;
|
172 |
+
border-radius: 6px;
|
173 |
+
float: right;
|
174 |
+
padding: 6px 10px;
|
175 |
+
}
|
176 |
+
|
177 |
+
div.tvc-feedback a:link {
|
178 |
+
color: #4D8C0F;
|
179 |
+
text-decoration: none;
|
180 |
+
}
|
181 |
+
|
182 |
+
div.tvc-feedback a:visited {
|
183 |
+
color: #555;
|
184 |
+
text-decoration: none;
|
185 |
+
}
|
186 |
+
|
187 |
+
div.tvc-feedback a:hover {
|
188 |
+
color: #3C3;
|
189 |
+
text-decoration: none;
|
190 |
+
}
|
191 |
+
|
192 |
+
table.fm-category-mapping-table th {
|
193 |
+
font-weight: 700;
|
194 |
+
padding: 9px;
|
195 |
+
}
|
196 |
+
|
197 |
+
table.fm-category-mapping-table {
|
198 |
+
clear: none;
|
199 |
+
display: table;
|
200 |
+
float: right;
|
201 |
+
height: 280px;
|
202 |
+
overflow-y: scroll;
|
203 |
+
width: 59%;
|
204 |
+
}
|
205 |
+
|
206 |
+
table.tvc-feed-main-input-table {
|
207 |
+
width: 100%;
|
208 |
+
}
|
209 |
+
|
210 |
+
table.fm-category-mapping-table td#shop-category {
|
211 |
+
color: #0073aa;
|
212 |
+
cursor: auto;
|
213 |
+
font-size: 14px !important;
|
214 |
+
font-weight: 600;
|
215 |
+
padding-left: 2px;
|
216 |
+
}
|
217 |
+
|
218 |
+
table.fm-category-mapping-table th#shop-category-selector {
|
219 |
+
vertical-align: top;
|
220 |
+
width: 2.2em;
|
221 |
+
}
|
222 |
+
|
223 |
+
td.channel-tile {
|
224 |
+
border: 1px solid #ccc;
|
225 |
+
box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
|
226 |
+
-moz-box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
|
227 |
+
-webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
|
228 |
+
max-width: 340px;
|
229 |
+
min-width: 250px;
|
230 |
+
vertical-align: top;
|
231 |
+
}
|
232 |
+
|
233 |
+
img.channel-thumbnail {
|
234 |
+
border: none;
|
235 |
+
max-width: 300px;
|
236 |
+
width: 100%;
|
237 |
+
}
|
238 |
+
|
239 |
+
div.channel-inner {
|
240 |
+
margin: 20px;
|
241 |
+
}
|
242 |
+
|
243 |
+
div.channel-version {
|
244 |
+
background-color: #eee;
|
245 |
+
border: 1px solid #dadada;
|
246 |
+
border-radius: 3px;
|
247 |
+
-webkit-border-radius: 3px;
|
248 |
+
-moz-border-radius: 3px;
|
249 |
+
color: #424242;
|
250 |
+
display: block;
|
251 |
+
font-weight: bold;
|
252 |
+
margin-bottom: 12px;
|
253 |
+
padding: 6px;
|
254 |
+
}
|
255 |
+
|
256 |
+
div#outdated {
|
257 |
+
color: red;
|
258 |
+
}
|
259 |
+
|
260 |
+
div.product-filter-condition-wrapper {
|
261 |
+
float: right;
|
262 |
+
font-size: 16px;
|
263 |
+
margin-top: 20px;
|
264 |
+
width: 59%;
|
265 |
+
}
|
266 |
+
|
267 |
+
section.tvc-main-input-wrapper {
|
268 |
+
float: left;
|
269 |
+
margin-top: 20px;
|
270 |
+
width: 40%;
|
271 |
+
}
|
272 |
+
|
273 |
+
tr.tvc-main-feed-input-row {
|
274 |
+
height: 47px;
|
275 |
+
}
|
276 |
+
|
277 |
+
table.fm-category-mapping-table thead, table.fm-category-mapping-table tbody {
|
278 |
+
float: left;
|
279 |
+
width: 100%;
|
280 |
+
}
|
281 |
+
|
282 |
+
table.fm-category-mapping-table tbody {
|
283 |
+
height: 280px;
|
284 |
+
overflow-y: scroll;
|
285 |
+
}
|
286 |
+
|
287 |
+
table.fm-category-mapping-table tr:nth-child(2n) td, table.fm-category-mapping-table tr:nth-child(2n) th {
|
288 |
+
background-color: #fcfcfc;
|
289 |
+
}
|
290 |
+
|
291 |
+
thead.fm-category-mapping-titles th {
|
292 |
+
font-weight: 400;
|
293 |
+
}
|
294 |
+
|
295 |
+
thead.fm-category-mapping-titles tr {
|
296 |
+
width: 98% !important;
|
297 |
+
}
|
298 |
+
|
299 |
+
table.fm-category-mapping-table td:first-child {
|
300 |
+
width: 16%;
|
301 |
+
}
|
302 |
+
|
303 |
+
table.fm-category-mapping-table tr {
|
304 |
+
display: table;
|
305 |
+
text-align: left;
|
306 |
+
width: 100%;
|
307 |
+
}
|
308 |
+
|
309 |
+
table.tvc-feed-main-input-table th {
|
310 |
+
padding-right: 0;
|
311 |
+
width: 40%;
|
312 |
+
}
|
313 |
+
|
314 |
+
table.tvc-feed-main-input-table input {
|
315 |
+
width: 90%;
|
316 |
+
}
|
317 |
+
|
318 |
+
table.tvc-feed-main-input-table input#aggregator, table.tvc-feed-main-input-table input#variations {
|
319 |
+
width: 10px;
|
320 |
+
}
|
321 |
+
|
322 |
+
table.tvc-feed-main-input-table select {
|
323 |
+
width: 90%;
|
324 |
+
}
|
325 |
+
|
326 |
+
.message-field {
|
327 |
+
font-size: 16px;
|
328 |
+
margin: 20px 0 3px 0;
|
329 |
+
}
|
330 |
+
|
331 |
+
#disposable-warning-message {
|
332 |
+
margin: 20px 0 3px 0;
|
333 |
+
}
|
334 |
+
|
335 |
+
button#disposable-notice-button {
|
336 |
+
position: relative;
|
337 |
+
}
|
338 |
+
|
339 |
+
.full-screen-message-field p {
|
340 |
+
color: red;
|
341 |
+
font-size: 17px;
|
342 |
+
margin: 20px 0 3px 0;
|
343 |
+
}
|
344 |
+
|
345 |
+
span.output-field-label {
|
346 |
+
background-color: #2ea2cc;
|
347 |
+
border-radius: 3px;
|
348 |
+
color: white;
|
349 |
+
margin-top: 4px;
|
350 |
+
padding: 4px 10px;
|
351 |
+
}
|
352 |
+
|
353 |
+
div.colw {
|
354 |
+
float: left;
|
355 |
+
padding: 5px;
|
356 |
+
}
|
357 |
+
|
358 |
+
div.edit-values-row {
|
359 |
+
float: left;
|
360 |
+
margin: 20px 10px 10px 30px;
|
361 |
+
width: 80%;
|
362 |
+
}
|
363 |
+
|
364 |
+
div.end-row {
|
365 |
+
clear: both;
|
366 |
+
}
|
367 |
+
|
368 |
+
div.field-table-row {
|
369 |
+
height: 20px;
|
370 |
+
}
|
371 |
+
|
372 |
+
div.field-table-row-edit-source {
|
373 |
+
clear: both;
|
374 |
+
float: left;
|
375 |
+
}
|
376 |
+
|
377 |
+
div.field-table-row-combined-selection {
|
378 |
+
left: -181px;
|
379 |
+
line-height: 26px;
|
380 |
+
margin: 5px;
|
381 |
+
position: relative;
|
382 |
+
width: 680px;
|
383 |
+
}
|
384 |
+
|
385 |
+
div.combined-wrapper {
|
386 |
+
line-height: 26px;
|
387 |
+
width: 100%;
|
388 |
+
}
|
389 |
+
|
390 |
+
div.or-selector {
|
391 |
+
line-height: 26px;
|
392 |
+
margin-top: 30px;
|
393 |
+
width: 120%;
|
394 |
+
}
|
395 |
+
|
396 |
+
div.dotted-top-line {
|
397 |
+
border-top-style: dashed;
|
398 |
+
border-top-color: #ccc;
|
399 |
+
border-top-width: 1px;
|
400 |
+
margin-top: 20px;
|
401 |
+
}
|
402 |
+
|
403 |
+
span.combined-field-row {
|
404 |
+
clear: left;
|
405 |
+
float: left;
|
406 |
+
}
|
407 |
+
|
408 |
+
input.free-category-text-input {
|
409 |
+
width: 90%;
|
410 |
+
}
|
411 |
+
|
412 |
+
div.button-wrapper {
|
413 |
+
clear: both;
|
414 |
+
}
|
415 |
+
|
416 |
+
.button-primary {
|
417 |
+
margin-top: 15px !important;
|
418 |
+
margin-right: 5px !important;
|
419 |
+
}
|
420 |
+
|
421 |
+
a.channel-button {
|
422 |
+
margin-right: 5px !important;
|
423 |
+
}
|
424 |
+
|
425 |
+
a.tvc-btn-small {
|
426 |
+
font-size: 13px;
|
427 |
+
}
|
428 |
+
|
429 |
+
a.tvc-rating-request {
|
430 |
+
color: #FFB900;
|
431 |
+
}
|
432 |
+
|
433 |
+
input.feed-list-lower-button {
|
434 |
+
position: relative;
|
435 |
+
margin-bottom: 10px!important;
|
436 |
+
}
|
437 |
+
|
438 |
+
div.select-control {
|
439 |
+
float: left;
|
440 |
+
margin: 0;
|
441 |
+
vertical-align: top;
|
442 |
+
}
|
443 |
+
|
444 |
+
div.static-value-control {
|
445 |
+
float: left;
|
446 |
+
}
|
447 |
+
#wpcontent{
|
448 |
+
height: 100%;
|
449 |
+
/*padding-left: 0 !important;*/
|
450 |
+
}
|
451 |
+
|
452 |
+
/*prgress info*/
|
453 |
+
.tvc-progressbar-wapper{
|
454 |
+
width: 97%;
|
455 |
+
margin: 10px auto;
|
456 |
+
text-align: center;
|
457 |
+
position: relative;
|
458 |
+
background-color: #fff;
|
459 |
+
padding: 11px;
|
460 |
+
}
|
461 |
+
.tvc-progressbar {
|
462 |
+
|
463 |
+
overflow: hidden;
|
464 |
+
counter-reset: step;
|
465 |
+
}
|
466 |
+
.tvc-progressbar .tvc-steps {
|
467 |
+
list-style-type: none;
|
468 |
+
color: #D2D2D2;
|
469 |
+
text-transform: capitalize;
|
470 |
+
font-size: 16px;
|
471 |
+
width: 33.33%;
|
472 |
+
float: left;
|
473 |
+
position: relative;
|
474 |
+
display: block;
|
475 |
+
}
|
476 |
+
.tvc-progressbar .tvc-steps .tvc-steps-icon{
|
477 |
+
display: inline-block;
|
478 |
+
float: left;
|
479 |
+
}
|
480 |
+
.tvc-progressbar .tvc-steps .tvc-steps-text{
|
481 |
+
display: inline-block;
|
482 |
+
|
483 |
+
float: left;
|
484 |
+
}
|
485 |
+
.tvc-progressbar .tvc-steps:before {
|
486 |
+
border: 2px solid #007bff;
|
487 |
+
color: #007bff;
|
488 |
+
content: '';
|
489 |
+
position: absolute;
|
490 |
+
counter-increment: step;
|
491 |
+
width: 43px;
|
492 |
+
line-height: 40px;
|
493 |
+
display: block;
|
494 |
+
font-size: 18px;
|
495 |
+
float: left;
|
496 |
+
background: transparent;
|
497 |
+
border-radius: 100%;
|
498 |
+
margin: 0 auto 5px auto;
|
499 |
+
border: 2px solid #ECECEC;
|
500 |
+
}
|
501 |
+
.tvc-progressbar .tvc-steps:nth-child(1):before {
|
502 |
+
content: "\f129";
|
503 |
+
font-family: 'FontAwesome';
|
504 |
+
}
|
505 |
+
.tvc-progressbar .tvc-steps:nth-child(2):before {
|
506 |
+
content: "\f013";
|
507 |
+
font-family: 'FontAwesome';
|
508 |
+
}
|
509 |
+
.tvc-progressbar .tvc-steps:nth-child(3):before {
|
510 |
+
content: "\f00c";
|
511 |
+
font-family: 'FontAwesome';
|
512 |
+
}
|
513 |
+
/*.tvc-progressbar .tvc-steps:after {
|
514 |
+
content: '';
|
515 |
+
width: 73%;
|
516 |
+
height: 2px;
|
517 |
+
background: #ECECEC;
|
518 |
+
position: absolute;
|
519 |
+
left: -35%;
|
520 |
+
top: 25px;
|
521 |
+
z-index: 1;
|
522 |
+
}
|
523 |
+
.tvc-progressbar .tvc-steps:first-child:after {
|
524 |
+
content: none;
|
525 |
+
}*/
|
526 |
+
.tvc-progressbar .tvc-steps lable{display: block; font-size: 22px;
|
527 |
+
color: #007bff; height: 54px; text-align: left;
|
528 |
+
margin: 6px 0 0 50px;}
|
529 |
+
.tvc-progressbar .tvc-steps span{display: block; text-align: left; font-size: 16px;
|
530 |
+
line-height: 24px;}
|
531 |
+
.tvc-progressbar .tvc-steps span img{margin-left: 5px; margin-right: 8px;
|
532 |
+
height: 10px;}
|
533 |
+
@media only screen and (min-width: 1200px){
|
534 |
+
.container{
|
535 |
+
margin-left: 8% !important;
|
536 |
+
width:auto;
|
537 |
+
}
|
538 |
+
.banner{
|
539 |
+
width:100%;
|
540 |
+
}
|
541 |
+
}
|
542 |
+
@media only screen and (min-width: 1920px){
|
543 |
+
.container{
|
544 |
+
margin-left: 6% !important;
|
545 |
+
width:auto;
|
546 |
+
}
|
547 |
+
|
548 |
+
}
|
css/tvc_admin-page.min.css
ADDED
@@ -0,0 +1,496 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.wp-core-ui select {
|
2 |
+
margin-bottom: 10px;
|
3 |
+
}
|
4 |
+
|
5 |
+
#tvc-attribute-map {
|
6 |
+
background: #fff;
|
7 |
+
padding: 20px;
|
8 |
+
border: 1px solid rgba(0, 0, 0, .125);
|
9 |
+
}
|
10 |
+
|
11 |
+
.bg-wrap {
|
12 |
+
background: #fff;
|
13 |
+
padding: 20px;
|
14 |
+
border: 1px solid rgba(0, 0, 0, .125);
|
15 |
+
overflow: auto;
|
16 |
+
}
|
17 |
+
|
18 |
+
.container {
|
19 |
+
margin-left: 8% !important;
|
20 |
+
width: auto;
|
21 |
+
}
|
22 |
+
|
23 |
+
#feed-spinner {
|
24 |
+
/*height: 50px;*/
|
25 |
+
left: 50%;
|
26 |
+
margin-left: -25px;
|
27 |
+
margin-top: -25px;
|
28 |
+
overflow: auto;
|
29 |
+
position: fixed;
|
30 |
+
text-align: center;
|
31 |
+
top: 35%;
|
32 |
+
/*width: 50px;*/
|
33 |
+
z-index: 1234
|
34 |
+
}
|
35 |
+
|
36 |
+
div.field-table-row-wrapper:nth-child(2n) {
|
37 |
+
background-color: #f5f5f5
|
38 |
+
}
|
39 |
+
|
40 |
+
div.field-table-row-wrapper {
|
41 |
+
display: block;
|
42 |
+
padding-bottom: 5px
|
43 |
+
}
|
44 |
+
|
45 |
+
div.filter-wrapper {
|
46 |
+
margin-top: 5px
|
47 |
+
}
|
48 |
+
|
49 |
+
aside.action-btn {
|
50 |
+
margin-left: 8px
|
51 |
+
}
|
52 |
+
|
53 |
+
.small-text {
|
54 |
+
width: 15px
|
55 |
+
}
|
56 |
+
|
57 |
+
.field-level {
|
58 |
+
clear: both;
|
59 |
+
font-size: 15px;
|
60 |
+
line-height: 30px;
|
61 |
+
padding-left: 5px
|
62 |
+
}
|
63 |
+
|
64 |
+
.value-options-condition-selector {
|
65 |
+
margin-left: 400px
|
66 |
+
}
|
67 |
+
|
68 |
+
.value-options-query-selector {
|
69 |
+
margin-bottom: 15px;
|
70 |
+
margin-left: 37%;
|
71 |
+
width: 65%
|
72 |
+
}
|
73 |
+
|
74 |
+
select.tvc-main-input-selector {
|
75 |
+
height: 33px;
|
76 |
+
max-width: 35rem
|
77 |
+
}
|
78 |
+
|
79 |
+
select.select-value-options {
|
80 |
+
height: 27px;
|
81 |
+
vertical-align: initial
|
82 |
+
}
|
83 |
+
|
84 |
+
select.align-left {
|
85 |
+
float: left
|
86 |
+
}
|
87 |
+
|
88 |
+
.condition-and-value-selector {
|
89 |
+
margin-left: 5px
|
90 |
+
}
|
91 |
+
|
92 |
+
div.condition-wrapper {
|
93 |
+
float: left;
|
94 |
+
line-height: 26px;
|
95 |
+
margin-bottom: 15px;
|
96 |
+
width: 100%
|
97 |
+
}
|
98 |
+
|
99 |
+
div.change-source-value-wrapper {
|
100 |
+
background-color: #e2e2e2;
|
101 |
+
float: left;
|
102 |
+
margin-left: 16%;
|
103 |
+
padding: 15px;
|
104 |
+
width: 81%
|
105 |
+
}
|
106 |
+
|
107 |
+
th#tvc-main-feed-input-label {
|
108 |
+
text-align: left;
|
109 |
+
width: 25%
|
110 |
+
}
|
111 |
+
|
112 |
+
th#tvc-main-feed-input-label label {
|
113 |
+
display: inline-block
|
114 |
+
}
|
115 |
+
|
116 |
+
div.edit-value-control {
|
117 |
+
float: right;
|
118 |
+
margin: -50px 10px
|
119 |
+
}
|
120 |
+
|
121 |
+
div.add-to-feed-column {
|
122 |
+
margin-top: 4px
|
123 |
+
}
|
124 |
+
|
125 |
+
div.tvc-header-wrapper {
|
126 |
+
padding-bottom: 10px
|
127 |
+
}
|
128 |
+
|
129 |
+
div.tvc-field-header-wrapper {
|
130 |
+
background-color: #e5e5e5;
|
131 |
+
height: 30px;
|
132 |
+
}
|
133 |
+
|
134 |
+
div#required-field-table {
|
135 |
+
border: 1px solid #e5e5e5;
|
136 |
+
border-top: none;
|
137 |
+
}
|
138 |
+
|
139 |
+
div#optional-field-table {
|
140 |
+
border: 1px solid #e5e5e5;
|
141 |
+
border-top: none;
|
142 |
+
}
|
143 |
+
|
144 |
+
div#new-optional-row {
|
145 |
+
border: 1px solid #e5e5e5;
|
146 |
+
border-top: none;
|
147 |
+
}
|
148 |
+
|
149 |
+
div.field-header {
|
150 |
+
float: left;
|
151 |
+
margin-bottom: 8px;
|
152 |
+
padding: 5px;
|
153 |
+
font-weight: 700;
|
154 |
+
}
|
155 |
+
|
156 |
+
.col10w {
|
157 |
+
width: 10%
|
158 |
+
}
|
159 |
+
|
160 |
+
.col30w {
|
161 |
+
width: 30%
|
162 |
+
}
|
163 |
+
|
164 |
+
.col20w {
|
165 |
+
width: 16%
|
166 |
+
}
|
167 |
+
|
168 |
+
.col40w {
|
169 |
+
width: 40%
|
170 |
+
}
|
171 |
+
|
172 |
+
.col55w {
|
173 |
+
width: 55%
|
174 |
+
}
|
175 |
+
|
176 |
+
.col80w {
|
177 |
+
width: 82%
|
178 |
+
}
|
179 |
+
|
180 |
+
.condition-selector {
|
181 |
+
width: 55%
|
182 |
+
}
|
183 |
+
|
184 |
+
div#category-mapping-header {
|
185 |
+
left: 15px;
|
186 |
+
position: relative
|
187 |
+
}
|
188 |
+
|
189 |
+
div.source-selector {
|
190 |
+
margin-right: 6%
|
191 |
+
}
|
192 |
+
|
193 |
+
div.tvc-feedback {
|
194 |
+
background-color: #fff;
|
195 |
+
border: 1px solid #e5e5e5;
|
196 |
+
border-radius: 6px;
|
197 |
+
float: right;
|
198 |
+
padding: 6px 10px
|
199 |
+
}
|
200 |
+
|
201 |
+
div.tvc-feedback a:link {
|
202 |
+
color: #4d8c0f;
|
203 |
+
text-decoration: none
|
204 |
+
}
|
205 |
+
|
206 |
+
div.tvc-feedback a:visited {
|
207 |
+
color: #555;
|
208 |
+
text-decoration: none
|
209 |
+
}
|
210 |
+
|
211 |
+
div.tvc-feedback a:hover {
|
212 |
+
color: #3C3;
|
213 |
+
text-decoration: none
|
214 |
+
}
|
215 |
+
|
216 |
+
table.fm-category-mapping-table th {
|
217 |
+
font-weight: 700;
|
218 |
+
padding: 9px
|
219 |
+
}
|
220 |
+
|
221 |
+
table.fm-category-mapping-table {
|
222 |
+
clear: none;
|
223 |
+
display: table;
|
224 |
+
float: right;
|
225 |
+
height: 280px;
|
226 |
+
overflow-y: scroll;
|
227 |
+
width: 50%
|
228 |
+
}
|
229 |
+
|
230 |
+
table.tvc-feed-main-input-table {
|
231 |
+
width: 100%
|
232 |
+
}
|
233 |
+
|
234 |
+
table.fm-category-mapping-table td#shop-category {
|
235 |
+
color: #0073aa;
|
236 |
+
cursor: auto;
|
237 |
+
font-size: 14px !important;
|
238 |
+
font-weight: 600;
|
239 |
+
padding-left: 2px
|
240 |
+
}
|
241 |
+
|
242 |
+
table.fm-category-mapping-table th#shop-category-selector {
|
243 |
+
vertical-align: top;
|
244 |
+
width: 2.2em
|
245 |
+
}
|
246 |
+
|
247 |
+
td.channel-tile {
|
248 |
+
border: 1px solid #ccc;
|
249 |
+
box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
|
250 |
+
-moz-box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
|
251 |
+
-webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.25);
|
252 |
+
max-width: 340px;
|
253 |
+
min-width: 250px;
|
254 |
+
vertical-align: top
|
255 |
+
}
|
256 |
+
|
257 |
+
img.channel-thumbnail {
|
258 |
+
border: 0;
|
259 |
+
max-width: 300px;
|
260 |
+
width: 100%
|
261 |
+
}
|
262 |
+
|
263 |
+
div.channel-inner {
|
264 |
+
margin: 20px
|
265 |
+
}
|
266 |
+
|
267 |
+
div.channel-version {
|
268 |
+
background-color: #eee;
|
269 |
+
border: 1px solid #dadada;
|
270 |
+
border-radius: 3px;
|
271 |
+
-webkit-border-radius: 3px;
|
272 |
+
-moz-border-radius: 3px;
|
273 |
+
color: #424242;
|
274 |
+
display: block;
|
275 |
+
font-weight: bold;
|
276 |
+
margin-bottom: 12px;
|
277 |
+
padding: 6px
|
278 |
+
}
|
279 |
+
|
280 |
+
div#outdated {
|
281 |
+
color: red
|
282 |
+
}
|
283 |
+
|
284 |
+
div.product-filter-condition-wrapper {
|
285 |
+
float: right;
|
286 |
+
font-size: 16px;
|
287 |
+
margin-top: 20px;
|
288 |
+
width: 59%
|
289 |
+
}
|
290 |
+
|
291 |
+
section.tvc-main-input-wrapper {
|
292 |
+
float: left;
|
293 |
+
margin-top: 20px;
|
294 |
+
width: 50%
|
295 |
+
}
|
296 |
+
|
297 |
+
tr.tvc-main-feed-input-row {
|
298 |
+
height: 47px
|
299 |
+
}
|
300 |
+
|
301 |
+
table.fm-category-mapping-table thead {
|
302 |
+
background: #e5e5e5;
|
303 |
+
}
|
304 |
+
|
305 |
+
table.fm-category-mapping-table thead, table.fm-category-mapping-table tbody {
|
306 |
+
float: left;
|
307 |
+
width: 100%
|
308 |
+
}
|
309 |
+
|
310 |
+
table.fm-category-mapping-table tbody {
|
311 |
+
height: 280px;
|
312 |
+
overflow-y: scroll
|
313 |
+
}
|
314 |
+
|
315 |
+
table.fm-category-mapping-table tr:nth-child(2n) td, table.fm-category-mapping-table tr:nth-child(2n) th {
|
316 |
+
background-color: #fcfcfc
|
317 |
+
}
|
318 |
+
|
319 |
+
thead.fm-category-mapping-titles th {
|
320 |
+
font-weight: 400
|
321 |
+
}
|
322 |
+
|
323 |
+
thead.fm-category-mapping-titles tr {
|
324 |
+
width: 98% !important
|
325 |
+
}
|
326 |
+
|
327 |
+
table.fm-category-mapping-table td:first-child {
|
328 |
+
width: 16%
|
329 |
+
}
|
330 |
+
|
331 |
+
table.fm-category-mapping-table tr {
|
332 |
+
display: table;
|
333 |
+
text-align: left;
|
334 |
+
width: 100%
|
335 |
+
}
|
336 |
+
|
337 |
+
table.tvc-feed-main-input-table th {
|
338 |
+
padding-right: 0;
|
339 |
+
width: 40%
|
340 |
+
}
|
341 |
+
|
342 |
+
table.tvc-feed-main-input-table input {
|
343 |
+
width: 90%
|
344 |
+
}
|
345 |
+
|
346 |
+
table.tvc-feed-main-input-table input#aggregator, table.tvc-feed-main-input-table input#variations {
|
347 |
+
width: 10px
|
348 |
+
}
|
349 |
+
|
350 |
+
table.tvc-feed-main-input-table select {
|
351 |
+
width: 90%;
|
352 |
+
margin-bottom: 10px;
|
353 |
+
}
|
354 |
+
|
355 |
+
.message-field {
|
356 |
+
font-size: 16px;
|
357 |
+
margin: 20px 0 3px 0
|
358 |
+
}
|
359 |
+
|
360 |
+
#disposable-warning-message {
|
361 |
+
margin: 20px 0 3px 0
|
362 |
+
}
|
363 |
+
|
364 |
+
button#disposable-notice-button {
|
365 |
+
position: relative
|
366 |
+
}
|
367 |
+
|
368 |
+
.full-screen-message-field p {
|
369 |
+
color: red;
|
370 |
+
font-size: 17px;
|
371 |
+
margin: 20px 0 3px 0
|
372 |
+
}
|
373 |
+
|
374 |
+
span.output-field-label {
|
375 |
+
border-radius: 3px;
|
376 |
+
color: #000;
|
377 |
+
margin-top: 4px;
|
378 |
+
padding: 4px 10px
|
379 |
+
}
|
380 |
+
|
381 |
+
div.colw {
|
382 |
+
float: left;
|
383 |
+
padding: 5px
|
384 |
+
}
|
385 |
+
|
386 |
+
div.edit-values-row {
|
387 |
+
float: left;
|
388 |
+
margin: 20px 10px 10px 30px;
|
389 |
+
width: 80%
|
390 |
+
}
|
391 |
+
|
392 |
+
div.end-row {
|
393 |
+
clear: both
|
394 |
+
}
|
395 |
+
|
396 |
+
div.field-table-row {
|
397 |
+
height: 20px
|
398 |
+
}
|
399 |
+
|
400 |
+
div.field-table-row-edit-source {
|
401 |
+
clear: both;
|
402 |
+
float: left
|
403 |
+
}
|
404 |
+
|
405 |
+
div.field-table-row-combined-selection {
|
406 |
+
left: -181px;
|
407 |
+
line-height: 26px;
|
408 |
+
margin: 5px;
|
409 |
+
position: relative;
|
410 |
+
width: 680px
|
411 |
+
}
|
412 |
+
|
413 |
+
div.combined-wrapper {
|
414 |
+
line-height: 26px;
|
415 |
+
width: 100%
|
416 |
+
}
|
417 |
+
|
418 |
+
div.or-selector {
|
419 |
+
line-height: 26px;
|
420 |
+
margin-top: 30px;
|
421 |
+
width: 120%
|
422 |
+
}
|
423 |
+
|
424 |
+
div.dotted-top-line {
|
425 |
+
border-top-style: dashed;
|
426 |
+
border-top-color: #ccc;
|
427 |
+
border-top-width: 1px;
|
428 |
+
margin-top: 20px
|
429 |
+
}
|
430 |
+
|
431 |
+
span.combined-field-row {
|
432 |
+
clear: left;
|
433 |
+
float: left
|
434 |
+
}
|
435 |
+
|
436 |
+
input.free-category-text-input {
|
437 |
+
width: 90%
|
438 |
+
}
|
439 |
+
|
440 |
+
div.button-wrapper {
|
441 |
+
clear: both
|
442 |
+
}
|
443 |
+
|
444 |
+
.button-primary {
|
445 |
+
margin-top: 25px !important;
|
446 |
+
margin-right: 5px !important
|
447 |
+
}
|
448 |
+
|
449 |
+
a.channel-button {
|
450 |
+
margin-right: 5px !important
|
451 |
+
}
|
452 |
+
|
453 |
+
a.tvc-btn-small {
|
454 |
+
font-size: 13px
|
455 |
+
}
|
456 |
+
|
457 |
+
a.tvc-rating-request {
|
458 |
+
color: #ffb900
|
459 |
+
}
|
460 |
+
|
461 |
+
input.feed-list-lower-button {
|
462 |
+
position: relative;
|
463 |
+
margin-bottom: 10px !important
|
464 |
+
}
|
465 |
+
|
466 |
+
div.select-control {
|
467 |
+
float: left;
|
468 |
+
margin: 0;
|
469 |
+
vertical-align: top
|
470 |
+
}
|
471 |
+
|
472 |
+
div.static-value-control {
|
473 |
+
float: left
|
474 |
+
}
|
475 |
+
|
476 |
+
#wpcontent{
|
477 |
+
height: 100%;
|
478 |
+
/*padding-left: 0 !important;*/
|
479 |
+
}
|
480 |
+
|
481 |
+
@media only screen and (min-width: 1200px){
|
482 |
+
.container{
|
483 |
+
margin-left: 8% !important;
|
484 |
+
width:auto;
|
485 |
+
}
|
486 |
+
.banner{
|
487 |
+
width:100%;
|
488 |
+
}
|
489 |
+
}
|
490 |
+
@media only screen and (min-width: 1920px){
|
491 |
+
.container{
|
492 |
+
margin-left: 6% !important;
|
493 |
+
width:auto;
|
494 |
+
}
|
495 |
+
|
496 |
+
}
|
css/tvc_setting-page.css
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
.container{
|
2 |
+
margin-left: 8% !important;
|
3 |
+
width:auto;
|
4 |
+
}
|
5 |
+
.banner{
|
6 |
+
width:100%;
|
7 |
+
}
|
8 |
+
|
9 |
+
@media only screen and (min-width: 1920px){
|
10 |
+
.container{
|
11 |
+
margin-left: 6% !important;
|
12 |
+
width:auto;
|
13 |
+
}
|
14 |
+
}
|
15 |
+
#feed-spinner {
|
16 |
+
/*height: 200px;*/ /*height of the spinner gif +2px to fix IE8 issue */
|
17 |
+
left: 50%;
|
18 |
+
margin-left: -25px; /* half width of the spinner gif */
|
19 |
+
margin-top: -25px; /* half height of the spinner gif */
|
20 |
+
overflow: auto;
|
21 |
+
position: fixed;
|
22 |
+
text-align: center;
|
23 |
+
top: 40%;
|
24 |
+
/*width: 200px;*/ /* width of the spinner gif */
|
25 |
+
z-index: 1234;
|
26 |
+
}
|
27 |
+
#footer-left{
|
28 |
+
display: none;
|
29 |
+
}
|
30 |
+
|
31 |
+
#tvc-backups th {
|
32 |
+
padding: 15px 10px;
|
33 |
+
}
|
34 |
+
|
35 |
+
#tvc-backups .tvc-backup-filename {
|
36 |
+
width: 180px;
|
37 |
+
}
|
38 |
+
|
39 |
+
#tvc-backups .tvc-backup-file_date {
|
40 |
+
width: 100px;
|
41 |
+
}
|
42 |
+
|
43 |
+
table.smallfat {
|
44 |
+
background: #fff;
|
45 |
+
border: 1px solid #e5e5e5;
|
46 |
+
box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
|
47 |
+
border-spacing: 0;
|
48 |
+
clear: both;
|
49 |
+
margin: 0;
|
50 |
+
}
|
51 |
+
|
52 |
+
#tvc_third_party_attr_keys {
|
53 |
+
width: 800px;
|
54 |
+
}
|
55 |
+
|
56 |
+
#tvc_notice_mailaddress {
|
57 |
+
width: 300px;
|
58 |
+
}
|
css/tvc_setting-page.min.css
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#feed-spinner {
|
2 |
+
/*height: 50px;*/
|
3 |
+
left: 50%;
|
4 |
+
margin-left: -25px;
|
5 |
+
margin-top: -25px;
|
6 |
+
overflow: auto;
|
7 |
+
position: fixed;
|
8 |
+
text-align: center;
|
9 |
+
top: 35%;
|
10 |
+
/*width: 50px;*/
|
11 |
+
z-index: 1234
|
12 |
+
}
|
13 |
+
|
14 |
+
#tvc-backups th {
|
15 |
+
padding: 15px 10px
|
16 |
+
}
|
17 |
+
|
18 |
+
#tvc-backups .tvc-backup-filename {
|
19 |
+
width: 180px
|
20 |
+
}
|
21 |
+
|
22 |
+
#tvc-backups .tvc-backup-file_date {
|
23 |
+
width: 100px
|
24 |
+
}
|
25 |
+
|
26 |
+
table.smallfat {
|
27 |
+
background: #fff;
|
28 |
+
border: 1px solid #e5e5e5;
|
29 |
+
box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
|
30 |
+
border-spacing: 0;
|
31 |
+
clear: both;
|
32 |
+
margin: 0
|
33 |
+
}
|
34 |
+
|
35 |
+
#tvc_third_party_attr_keys {
|
36 |
+
width: 800px
|
37 |
+
}
|
38 |
+
|
39 |
+
#tvc_notice_mailaddress {
|
40 |
+
width: 300px
|
41 |
+
}
|
enhanced-ecommerce-google-analytics.php
CHANGED
File without changes
|
google_ads_php.ini
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[GOOGLE_ADS]
|
2 |
+
name = "Google Ads"
|
3 |
+
developerToken = "R0IEth5fQ1Ac59qB2Wf8Aw"
|
4 |
+
loginCustomerId = "9704619790"
|
5 |
+
|
6 |
+
[LOGGING]
|
7 |
+
logFilePath = ""
|
8 |
+
|
9 |
+
[OAUTH2]
|
10 |
+
clientId = "854883711805-4bm7ik0lq2jcdvdk0qu8sgtd4jdc1k7o.apps.googleusercontent.com"
|
11 |
+
clientSecret = "mwgFJ25-FMPEyeNtI-TIMJIZ"
|
12 |
+
refreshToken = "1//0glkEtsa8PNuwCgYIARAAGBASNwF-L9IrBZQjIINEw2MMO_M_mRdKwoNCBwJtHXtahh5Bj4oQR01ErmhaBB2TqE68rkP8JaELISU"
|
13 |
+
developerToken = "R0IEth5fQ1Ac59qB2Wf8Aw"
|
14 |
+
|
images/ajax-loader.gif
ADDED
Binary file
|
includes/application/class-feed-master.php
ADDED
@@ -0,0 +1,676 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* Defines the plugin name, version, and two examples hooks for how to
|
6 |
+
* enqueue the admin-specific stylesheet and JavaScript.
|
7 |
+
*
|
8 |
+
* @package Google Product Feed Manager
|
9 |
+
* @subpackage Google Product Feed Manager/Application/Classes
|
10 |
+
* @author Chetan Rode <chetan@tatvic.com>
|
11 |
+
*/
|
12 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
13 |
+
exit;
|
14 |
+
}
|
15 |
+
|
16 |
+
if ( ! class_exists( 'TVC_Feed_Master_Class' ) ) :
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Feed Master Class
|
20 |
+
*
|
21 |
+
* @since 2.0.0
|
22 |
+
*/
|
23 |
+
class TVC_Feed_Master_Class {
|
24 |
+
|
25 |
+
use TVC_Processing_Support;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Contains the general feed data
|
29 |
+
*
|
30 |
+
* @var object
|
31 |
+
*/
|
32 |
+
protected $_feed = null;
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Contains the feed is
|
36 |
+
*
|
37 |
+
* @var string
|
38 |
+
*/
|
39 |
+
protected $_feed_id;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Instantiation of global background process class
|
43 |
+
*
|
44 |
+
* @var stdClass
|
45 |
+
*/
|
46 |
+
protected $_background_process;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Placeholder for the correct channel class
|
50 |
+
*
|
51 |
+
* @var stdClass
|
52 |
+
*/
|
53 |
+
protected $_channel_class;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Placeholder for the TVC_Data_Class
|
57 |
+
*
|
58 |
+
* @var stdClass
|
59 |
+
*/
|
60 |
+
protected $_data_class;
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Path and name of the feed file
|
64 |
+
*
|
65 |
+
* @var string
|
66 |
+
*/
|
67 |
+
protected $_feed_file_path;
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Initiate new Feed Master class.
|
71 |
+
*
|
72 |
+
* @param string $feed_id The id of the feed. Default 0
|
73 |
+
*
|
74 |
+
* @global stdClass $background_process
|
75 |
+
*
|
76 |
+
*/
|
77 |
+
public function __construct( $feed_id = '0' ) {
|
78 |
+
$query_class = new TVC_Queries();
|
79 |
+
|
80 |
+
/**
|
81 |
+
* when this construct is called from a channel class, it will not specify the feed_id so the default 0 is used
|
82 |
+
* in that case the feed_type_id will always be 1
|
83 |
+
*/
|
84 |
+
|
85 |
+
$feed_type_id = $feed_id > 0 ? $query_class->get_feed_type_id( $feed_id ) : '1';
|
86 |
+
|
87 |
+
$background_class = apply_filters( 'tvc_background_class', 'TVC_Feed_Processor', $feed_type_id );
|
88 |
+
|
89 |
+
$this->_background_process = new $background_class();
|
90 |
+
$this->_data_class = new TVC_Data();
|
91 |
+
}
|
92 |
+
|
93 |
+
/**
|
94 |
+
* The update feed file function that starts the update process
|
95 |
+
*
|
96 |
+
* @param bool $silent (default true)
|
97 |
+
*
|
98 |
+
* @return string|void or false
|
99 |
+
*/
|
100 |
+
public function update_feed_file( $silent = true ) {
|
101 |
+
|
102 |
+
$feed_id = TVC_Feed_Controller::get_next_id_from_feed_queue();
|
103 |
+
|
104 |
+
do_action( 'tvc_feed_process_prepared', $feed_id, $silent );
|
105 |
+
|
106 |
+
if ( false === $feed_id ) {
|
107 |
+
return false;
|
108 |
+
}
|
109 |
+
|
110 |
+
if ( $silent ) {
|
111 |
+
set_transient( 'tvc_running_silent', true, TVC_TRANSIENT_LIVE );
|
112 |
+
}
|
113 |
+
|
114 |
+
$feed_data = $this->_data_class->get_feed_data( $feed_id );
|
115 |
+
|
116 |
+
if ( ! $feed_data ) {
|
117 |
+
do_action( 'tvc_feed_generation_message', $feed_id, 'The update_feed_file function failed to get the feed data', 'ERROR' );
|
118 |
+
if ( ! $silent ) {
|
119 |
+
_e( '1428 - Failed to load the feed data, please to generate a feed in the foreground mode (see Settings page) and then try the background mode again.', 'tvc-product-feed-manager' );
|
120 |
+
}
|
121 |
+
|
122 |
+
return false;
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* store the feed data in a property
|
127 |
+
*/
|
128 |
+
$this->_feed = $feed_data;
|
129 |
+
|
130 |
+
/**
|
131 |
+
* only one feed can be processing so if other feeds than the current feed are on a processing
|
132 |
+
* status, set these to an error status
|
133 |
+
*/
|
134 |
+
$this->_data_class->check_for_failed_feeds( $this->_feed->feedId );
|
135 |
+
|
136 |
+
$prepare_update = $this->prepare_feed_file_update( $silent );
|
137 |
+
|
138 |
+
if ( true !== $prepare_update ) {
|
139 |
+
if ( ! $silent ) {
|
140 |
+
echo $prepare_update;
|
141 |
+
}
|
142 |
+
|
143 |
+
return false;
|
144 |
+
}
|
145 |
+
|
146 |
+
TVC_Feed_Controller::set_feed_processing_flag( true );
|
147 |
+
|
148 |
+
$this->prepare_background_process();
|
149 |
+
|
150 |
+
$this->fill_the_background_queue();
|
151 |
+
|
152 |
+
$this->activate_feed_file_update( $this->_feed->feedId );
|
153 |
+
|
154 |
+
delete_transient( 'tvc_running_silent' );
|
155 |
+
|
156 |
+
if ( ! $silent ) {
|
157 |
+
echo 'started_processing';
|
158 |
+
}
|
159 |
+
}
|
160 |
+
|
161 |
+
public function feed_status_check( $feed_id ) {
|
162 |
+
$queries_class = new TVC_Queries();
|
163 |
+
|
164 |
+
$current_feed_status = $queries_class->get_feed_status_data( $feed_id );
|
165 |
+
|
166 |
+
$current_feed_status['feed_type_name'] = tvc_list_feed_type_text()[ $current_feed_status['feed_type_id'] ];
|
167 |
+
|
168 |
+
if ( '3' === $current_feed_status['status_id'] ) { // status still processing
|
169 |
+
// get file name, including path
|
170 |
+
$file_extension = function_exists( 'get_file_type' ) ? get_file_type( $current_feed_status['channel_id'] ) : 'xml';
|
171 |
+
$feed_file = tvc_get_file_path( $current_feed_status['title'] . '.' . $file_extension );
|
172 |
+
|
173 |
+
// if it is, set the feed status to fail and change the $current_feed_status['status_id'] to 6
|
174 |
+
if ( TVC_Feed_Controller::feed_processing_failed( $feed_file ) ) {
|
175 |
+
// change the status of the feed to failed processing
|
176 |
+
$this->_data_class->update_feed_status( $feed_id, 6 ); // feed status to failed
|
177 |
+
|
178 |
+
// update the current_feed_status variable before returning
|
179 |
+
$current_feed_status['status_id'] = '6';
|
180 |
+
|
181 |
+
// clear this feed from the feed queue
|
182 |
+
TVC_Feed_Controller::remove_id_from_feed_queue( $feed_id );
|
183 |
+
TVC_Feed_Controller::set_feed_processing_flag( false );
|
184 |
+
|
185 |
+
// if running silent (automatic feed update) inform the user about the failed feed
|
186 |
+
if ( get_transient( 'tvc_running_silent' ) ) {
|
187 |
+
TVC_Email::send_feed_failed_message();
|
188 |
+
}
|
189 |
+
|
190 |
+
if ( ! TVC_Feed_Controller::feed_queue_is_empty() ) {
|
191 |
+
$next_feed_id = TVC_Feed_Controller::get_next_id_from_feed_queue();
|
192 |
+
|
193 |
+
if ( $next_feed_id ) {
|
194 |
+
// so there is another feed in the queue
|
195 |
+
$feed_master_class = new TVC_Feed_Master_Class( $next_feed_id );
|
196 |
+
$feed_master_class->update_feed_file();
|
197 |
+
}
|
198 |
+
}
|
199 |
+
|
200 |
+
do_action( 'tvc_feed_processing_failed_file_size_stopped_increasing', $feed_id, TVC_Feed_Controller::nr_ids_remaining_in_queue() );
|
201 |
+
do_action( 'tvc_register_feed_url', $feed_id, $feed_file );
|
202 |
+
}
|
203 |
+
|
204 |
+
return $current_feed_status;
|
205 |
+
} else {
|
206 |
+
return $current_feed_status;
|
207 |
+
}
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Perform all preparations for the feed update starts
|
212 |
+
*
|
213 |
+
* @param bool $silent (default true)
|
214 |
+
*
|
215 |
+
* @return bool true if feed file has been updated successfully
|
216 |
+
*/
|
217 |
+
private function prepare_feed_file_update( $silent ) {
|
218 |
+
// prepare the folder structure to support saving feed files
|
219 |
+
if ( ! file_exists( TVC_FEEDS_DIR ) ) {
|
220 |
+
TVC_Folders::make_feed_support_folder();
|
221 |
+
}
|
222 |
+
|
223 |
+
if ( ! is_writable( TVC_FEEDS_DIR ) ) {
|
224 |
+
/* translators: %s: Folder where the feeds are stored */
|
225 |
+
return sprintf( esc_html__( '1430 - %s is not a writable folder. Make sure you have admin rights to this folder.', 'tvc-product-feed-manager' ), TVC_FEEDS_DIR );
|
226 |
+
}
|
227 |
+
|
228 |
+
$initial_feed_status = $this->_feed->status;
|
229 |
+
|
230 |
+
if ( ! $this->set_properties() ) {
|
231 |
+
$message = sprintf( 'Failed to set the properties of feed %s.', $this->_feed->feedId );
|
232 |
+
do_action( 'tvc_feed_generation_message', $this->_feed->feedId, $message, 'ERROR' );
|
233 |
+
|
234 |
+
return false;
|
235 |
+
}
|
236 |
+
|
237 |
+
$this->_data_class->set_nr_of_feed_products( $this->_feed->feedId, '0' ); // 0 products
|
238 |
+
$this->_data_class->update_feed_status( $this->_feed->feedId, 3 ); // set status to "Processing"
|
239 |
+
|
240 |
+
$file_extension = function_exists( 'get_file_type' ) ? get_file_type( $this->_feed->channel ) : 'xml';
|
241 |
+
|
242 |
+
$this->_feed_file_path = tvc_get_file_path( $this->_feed->title . '.' . $file_extension );
|
243 |
+
|
244 |
+
// clear the existing feed
|
245 |
+
file_put_contents( $this->_feed_file_path, '' );
|
246 |
+
|
247 |
+
// clear the file size checker
|
248 |
+
delete_transient( 'tvc_feed_file_size' );
|
249 |
+
|
250 |
+
// clear the list of processed products @since 2.10.0.
|
251 |
+
delete_option( 'tvc_processed_products' );
|
252 |
+
|
253 |
+
$channel_class = new TVC_Channel();
|
254 |
+
$channel_name = $channel_class->get_channel_short_name( $this->_feed->channel );
|
255 |
+
|
256 |
+
$logger_message = sprintf( 'Feed %s is a %s feed stored as %s, with an original feed status %s.', $this->_feed->feedId, $channel_name, $this->_feed_file_path, $initial_feed_status );
|
257 |
+
do_action( 'tvc_feed_generation_message', $this->_feed->feedId, $logger_message );
|
258 |
+
|
259 |
+
return true;
|
260 |
+
}
|
261 |
+
|
262 |
+
/**
|
263 |
+
* Store common product metadata in the Background Process properties
|
264 |
+
*/
|
265 |
+
private function prepare_background_process() {
|
266 |
+
// start counting from zero
|
267 |
+
delete_option( 'tvc_processed_products' );
|
268 |
+
|
269 |
+
$this->_background_process->set_feed_data( $this->_feed );
|
270 |
+
$this->_background_process->set_file_path( $this->_feed_file_path );
|
271 |
+
$this->_background_process->set_pre_data( $this->get_required_pre_data() );
|
272 |
+
$this->_background_process->set_channel_details( $this->get_channel_details() );
|
273 |
+
$this->_background_process->set_relations_table( $this->get_channel_to_woocommerce_field_relations() );
|
274 |
+
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* Fills the background queue
|
278 |
+
*/
|
279 |
+
private function fill_the_background_queue() {
|
280 |
+
// start with an empty queue
|
281 |
+
$this->_background_process->clear_the_queue();
|
282 |
+
$sw_status_control = 30000 * 3.3;
|
283 |
+
$product_counter = 0;
|
284 |
+
|
285 |
+
// add the header to the queue
|
286 |
+
$header_string = $this->get_feed_header();
|
287 |
+
$this->_background_process->push_to_queue( array( 'file_format_line' => $header_string ) );
|
288 |
+
|
289 |
+
do {
|
290 |
+
$product_ids = $this->get_product_ids_for_feed();
|
291 |
+
|
292 |
+
// add the product ids to the queue
|
293 |
+
foreach ( $product_ids as $product_id ) {
|
294 |
+
$this->_background_process->push_to_queue( $product_id );
|
295 |
+
|
296 |
+
$product_counter++;
|
297 |
+
|
298 |
+
if ( $product_counter > $sw_status_control ) { // HWOTBERH
|
299 |
+
break;
|
300 |
+
}
|
301 |
+
}
|
302 |
+
} while ( ! empty( $product_ids ) && $sw_status_control > $product_counter );
|
303 |
+
|
304 |
+
delete_transient( 'tvc_start_product_id' );
|
305 |
+
|
306 |
+
// implement the tvc_feed_ids_in_queue filter on the queue.
|
307 |
+
$this->_background_process->apply_filter_to_queue( $this->_feed->feedId );
|
308 |
+
|
309 |
+
do_action( 'tvc_feed_queue_filled', $this->_feed->feedId, $product_counter );
|
310 |
+
|
311 |
+
$product_ids = null;
|
312 |
+
|
313 |
+
$file_extension = function_exists( 'get_file_type' ) ? get_file_type( $this->_feed->channel ) : 'xml';
|
314 |
+
|
315 |
+
// add the xml footer to the queue
|
316 |
+
if ( 'xml' === $file_extension ) {
|
317 |
+
$this->_background_process->push_to_queue(
|
318 |
+
array(
|
319 |
+
'file_format_line' => apply_filters(
|
320 |
+
'tvc_footer_string',
|
321 |
+
$this->_channel_class->footer(),
|
322 |
+
$this->_feed->feedId,
|
323 |
+
$this->_feed->feedTypeId
|
324 |
+
),
|
325 |
+
)
|
326 |
+
);
|
327 |
+
}
|
328 |
+
}
|
329 |
+
|
330 |
+
/**
|
331 |
+
* Start the feed update process in the background
|
332 |
+
*
|
333 |
+
* @param string $feed_id
|
334 |
+
*/
|
335 |
+
private function activate_feed_file_update( $feed_id ) {
|
336 |
+
// save the queue data and then run the tvc-background-process dispatch function
|
337 |
+
$this->_background_process->save( $this->_feed->feedId )->dispatch( $feed_id );
|
338 |
+
}
|
339 |
+
|
340 |
+
/**
|
341 |
+
* Set all class properties
|
342 |
+
*
|
343 |
+
* @return bool
|
344 |
+
*/
|
345 |
+
private function set_properties() {
|
346 |
+
// some channels do not use channels and leave the main category empty which causes issues
|
347 |
+
if ( function_exists( 'channel_uses_category' ) && ! channel_uses_category( $this->_feed->channel ) ) {
|
348 |
+
$this->_feed->mainCategory = 'No Category Required';
|
349 |
+
}
|
350 |
+
|
351 |
+
// some channels only accept category id numbers, for these channels retrieve the category numbers
|
352 |
+
if ( stripos( strrev( $this->_feed->mainCategory ), ')' ) === 0 ) {
|
353 |
+
$start = stripos( $this->_feed->mainCategory, '(' ) + 1;
|
354 |
+
$end = stripos( $this->_feed->mainCategory, '(' ) - $start;
|
355 |
+
$this->_feed->mainCategory = substr( $this->_feed->mainCategory, $start, $end );
|
356 |
+
}
|
357 |
+
|
358 |
+
// instantiate the correct channel class
|
359 |
+
$this->_channel_class = new TVC_Google_Feed_Class();
|
360 |
+
return true;
|
361 |
+
}
|
362 |
+
|
363 |
+
/**
|
364 |
+
* Returns the header that is correct for the selected feed type
|
365 |
+
*
|
366 |
+
* @return string
|
367 |
+
*/
|
368 |
+
private function get_feed_header() {
|
369 |
+
$header_string = '';
|
370 |
+
|
371 |
+
if ( $this->_feed->channel ) {
|
372 |
+
$file_extension = function_exists( 'get_file_type' ) ? get_file_type( $this->_feed->channel ) : 'xml';
|
373 |
+
if ( '1' === $this->_feed->channel && ! empty( $this->_feed->feedTitle ) ) {
|
374 |
+
$header_string = $this->_channel_class->header( $this->_feed->feedTitle, $this->_feed->feedDescription );
|
375 |
+
} elseif ( 'xml' === $file_extension ) {
|
376 |
+
$header_string = $this->_channel_class->header( $this->_feed->title );
|
377 |
+
} elseif ( 'txt' === $file_extension ) {
|
378 |
+
$header_string = $this->make_tab_delimited_string_from_data_array( $this->get_active_fields() );
|
379 |
+
} elseif ( 'csv' === $file_extension ) {
|
380 |
+
$csv_sep = apply_filters( 'tvc_csv_separator', get_correct_csv_header_separator( $this->_feed->channel ) );
|
381 |
+
$string = $this->make_csv_header_string( $this->get_active_fields(), $csv_sep );
|
382 |
+
$header_string = $this->_channel_class->header( $string );
|
383 |
+
}
|
384 |
+
}
|
385 |
+
|
386 |
+
return apply_filters( 'tvc_header_string', $header_string, $this->_feed->feedId, $this->_feed->feedTypeId );
|
387 |
+
}
|
388 |
+
|
389 |
+
/**
|
390 |
+
* ALERT! has a javascript equivalent in channel-functions.js called setAttributeStatus();
|
391 |
+
*/
|
392 |
+
|
393 |
+
/**
|
394 |
+
* sets the activity status of a specific attribute to true or false depending on its level
|
395 |
+
*
|
396 |
+
* @param int $field_level
|
397 |
+
* @param string $field_value
|
398 |
+
*
|
399 |
+
* @return boolean
|
400 |
+
*/
|
401 |
+
protected function set_attribute_status( $field_level, $field_value ) {
|
402 |
+
if ( $field_level > 0 && $field_level < 3 ) {
|
403 |
+
return true;
|
404 |
+
}
|
405 |
+
$clean_field_value = trim( $field_value );
|
406 |
+
if ( ! empty( $clean_field_value ) ) {
|
407 |
+
return true;
|
408 |
+
}
|
409 |
+
|
410 |
+
return false;
|
411 |
+
}
|
412 |
+
|
413 |
+
/**
|
414 |
+
* Produces an array with the ids of all products that should be added into the feed
|
415 |
+
*
|
416 |
+
* @return array with ids
|
417 |
+
*/
|
418 |
+
private function get_product_ids_for_feed() {
|
419 |
+
$queries_class = new TVC_Queries();
|
420 |
+
|
421 |
+
$selected_categories = apply_filters( 'tvc_selected_categories', $this->make_category_selection_string(), $this->_feed->feedId );
|
422 |
+
|
423 |
+
$include_variations = '1' === $this->_feed->includeVariations ? true : false;
|
424 |
+
|
425 |
+
$products = $queries_class->get_post_ids( $selected_categories, $include_variations );
|
426 |
+
|
427 |
+
array_filter( $products ); // just to make sure, remove all empty elements
|
428 |
+
|
429 |
+
return $products;
|
430 |
+
}
|
431 |
+
|
432 |
+
/**
|
433 |
+
* Returns a comma separated string with selected category numbers to be used as part of a query
|
434 |
+
*
|
435 |
+
* @return string
|
436 |
+
*/
|
437 |
+
private function make_category_selection_string() {
|
438 |
+
$category_selection_string = '';
|
439 |
+
$category_mapping = json_decode( $this->_feed->categoryMapping );
|
440 |
+
|
441 |
+
if ( ! empty( $category_mapping ) ) {
|
442 |
+
foreach ( $category_mapping as $category ) {
|
443 |
+
$category_selection_string .= $category->shopCategoryId . ', '; // phpcs:ignore
|
444 |
+
}
|
445 |
+
}
|
446 |
+
|
447 |
+
return $category_selection_string ? substr( $category_selection_string, 0, - 2 ) : '';
|
448 |
+
}
|
449 |
+
|
450 |
+
/**
|
451 |
+
* Get all general data required to make a feed
|
452 |
+
*
|
453 |
+
* @return array
|
454 |
+
*/
|
455 |
+
private function get_required_pre_data() {
|
456 |
+
// get the feed query string if the user has added to filter out specific products from the feed (Paid version only)
|
457 |
+
$feed_filter = $this->_data_class->get_filter_query( $this->_feed->feedId );
|
458 |
+
|
459 |
+
// should the feed include product variations?
|
460 |
+
$include_variations = '1' === $this->_feed->includeVariations ? true : false;
|
461 |
+
|
462 |
+
// get an array with all the field names that are required to make the feed (including the source fields, fields for the queries and fields for static data)
|
463 |
+
$required_column_names = $this->get_column_names_required_for_feed( $feed_filter );
|
464 |
+
|
465 |
+
// get the fields that are active and have to go into the feed
|
466 |
+
$active_fields = $this->get_active_fields();
|
467 |
+
|
468 |
+
$database_fields = $this->get_database_fields( $required_column_names );
|
469 |
+
|
470 |
+
return array(
|
471 |
+
'filters' => $feed_filter,
|
472 |
+
'include_vars' => $include_variations,
|
473 |
+
'column_names' => $required_column_names,
|
474 |
+
'active_fields' => $active_fields,
|
475 |
+
'database_fields' => $database_fields,
|
476 |
+
);
|
477 |
+
}
|
478 |
+
|
479 |
+
/**
|
480 |
+
* Get category name and description name from the active channel
|
481 |
+
*
|
482 |
+
* @return array
|
483 |
+
*/
|
484 |
+
private function get_channel_details() {
|
485 |
+
return function_exists( 'channel_file_text_data' ) ? channel_file_text_data( $this->_feed->channel ) :
|
486 |
+
array(
|
487 |
+
'channel_id' => $this->_feed->channel,
|
488 |
+
'category_name' => 'google_product_category',
|
489 |
+
'description_name' => 'description',
|
490 |
+
);
|
491 |
+
}
|
492 |
+
|
493 |
+
/**
|
494 |
+
* returns the column names from the database that are required to get the data necessary to make the feed
|
495 |
+
*
|
496 |
+
* @param object $feed_filter_object
|
497 |
+
*
|
498 |
+
* @return array
|
499 |
+
*/
|
500 |
+
private function get_column_names_required_for_feed( $feed_filter_object ) {
|
501 |
+
$support_class = new TVC_Feed_Support();
|
502 |
+
|
503 |
+
$fields = array();
|
504 |
+
$filter_columns = $support_class->get_column_names_from_feed_filter_array( $feed_filter_object );
|
505 |
+
|
506 |
+
foreach ( $this->_feed->attributes as $attribute ) {
|
507 |
+
if ( 'category_mapping' !== $attribute->fieldName ) {
|
508 |
+
$column_names = $this->get_db_column_name_from_attribute( $attribute );
|
509 |
+
foreach ( $column_names as $name ) {
|
510 |
+
if ( ! empty( $name ) ) {
|
511 |
+
array_push( $fields, $name );
|
512 |
+
}
|
513 |
+
}
|
514 |
+
}
|
515 |
+
}
|
516 |
+
|
517 |
+
$result = array_unique( array_merge( $fields, $filter_columns ) ); // remove doubles
|
518 |
+
|
519 |
+
if ( empty( $result ) ) {
|
520 |
+
tvc_write_log_file( 'Function get_column_names_required_for_feed returned zero columns' );
|
521 |
+
}
|
522 |
+
|
523 |
+
return array_merge( $result ); // and resort the result before returning
|
524 |
+
}
|
525 |
+
|
526 |
+
/**
|
527 |
+
* returns all active column names that are stored in the feed attributes
|
528 |
+
*
|
529 |
+
* @param array $attribute
|
530 |
+
*
|
531 |
+
* @return array
|
532 |
+
*/
|
533 |
+
public function get_db_column_name_from_attribute( $attribute ) {
|
534 |
+
$column_names = array();
|
535 |
+
|
536 |
+
if ( property_exists( $attribute, 'isActive' ) && $attribute->isActive ) { // only select the active attributes
|
537 |
+
// source columns
|
538 |
+
if ( ! empty( $attribute->value ) ) {
|
539 |
+
$source_columns = $this->get_source_columns_from_attribute_value( $attribute->value );
|
540 |
+
$condition_columns = $this->get_condition_columns_from_attribute_value( $attribute->value );
|
541 |
+
$query_columns = $this->get_queries_columns_from_attribute_value( $attribute->value );
|
542 |
+
|
543 |
+
// TODO: I think the first $column_names array can be removed from the array_merge
|
544 |
+
$column_names = array_merge( $column_names, $source_columns, $condition_columns, $query_columns );
|
545 |
+
}
|
546 |
+
|
547 |
+
// advised sources
|
548 |
+
if ( ! empty( $attribute->advisedSource )
|
549 |
+
&& strpos( $attribute->advisedSource, esc_html__( 'Fill with a static value', 'tvc-product-feed-manager' ) ) === false
|
550 |
+
&& strpos( $attribute->advisedSource, esc_html__( 'Use the settings in the Merchant Center', 'tvc-product-feed-manager' ) ) === false ) {
|
551 |
+
|
552 |
+
// add the relevant advised sources
|
553 |
+
array_push( $column_names, $attribute->advisedSource );
|
554 |
+
} elseif ( property_exists( $attribute, 'advisedSource' )
|
555 |
+
&& strpos( $attribute->advisedSource, esc_html__( 'Use the settings in the Merchant Center', 'tvc-product-feed-manager' ) ) !== false ) {
|
556 |
+
|
557 |
+
array_push( $column_names, 'woo_shipping' );
|
558 |
+
}
|
559 |
+
}
|
560 |
+
return $column_names;
|
561 |
+
}
|
562 |
+
|
563 |
+
/**
|
564 |
+
* extract the active fields from the attributes
|
565 |
+
*
|
566 |
+
* @return array
|
567 |
+
*/
|
568 |
+
private function get_active_fields() {
|
569 |
+
$active_fields = array();
|
570 |
+
|
571 |
+
foreach ( $this->_feed->attributes as $attribute ) {
|
572 |
+
if ( $attribute->isActive && 'category_mapping' !== $attribute->fieldName ) {
|
573 |
+
$push = false;
|
574 |
+
|
575 |
+
if ( '1' === $attribute->fieldLevel ) {
|
576 |
+
$push = true;
|
577 |
+
} else {
|
578 |
+
$value_object = property_exists( $attribute, 'value' ) ? json_decode( $attribute->value ) : new stdClass();
|
579 |
+
|
580 |
+
if ( ! empty( $attribute->value ) && property_exists( $value_object, 'm' ) && property_exists( $value_object->m[0], 's' ) ) {
|
581 |
+
$push = true;
|
582 |
+
} elseif ( ! empty( $attribute->advisedSource ) ) {
|
583 |
+
$push = true;
|
584 |
+
} elseif ( ! empty( $attribute->value ) && property_exists( $value_object, 't' ) ) {
|
585 |
+
$push = true;
|
586 |
+
} elseif ( ! empty( $attribute->value ) && property_exists( $value_object, 'v' ) ) {
|
587 |
+
$push = true;
|
588 |
+
}
|
589 |
+
}
|
590 |
+
|
591 |
+
if ( true === $push ) {
|
592 |
+
array_push( $active_fields, $attribute->fieldName );
|
593 |
+
}
|
594 |
+
}
|
595 |
+
}
|
596 |
+
|
597 |
+
if ( empty( $active_fields ) ) {
|
598 |
+
tvc_write_log_file( 'Function get_active_fields returned zero fields.' );
|
599 |
+
}
|
600 |
+
|
601 |
+
return $active_fields;
|
602 |
+
}
|
603 |
+
|
604 |
+
/**
|
605 |
+
* gather all required column names from the database
|
606 |
+
*
|
607 |
+
* @param array $active_field_names
|
608 |
+
*
|
609 |
+
* @return array
|
610 |
+
*/
|
611 |
+
private function get_database_fields( $active_field_names ) {
|
612 |
+
$queries_class = new TVC_Queries();
|
613 |
+
|
614 |
+
$post_fields = array();
|
615 |
+
$meta_fields = array();
|
616 |
+
$custom_fields = array();
|
617 |
+
$active_custom_fields = array();
|
618 |
+
$active_third_party_custom_fields = array();
|
619 |
+
$post_columns_string = '';
|
620 |
+
|
621 |
+
$columns_in_post_table = $queries_class->get_columns_from_post_table(); // get all post table column names
|
622 |
+
$all_custom_columns = $queries_class->get_custom_product_attributes(); // get all custom name labels
|
623 |
+
$third_party_custom_fields = $this->_data_class->get_third_party_custom_fields();
|
624 |
+
|
625 |
+
// convert the query results to an array with only the name labels
|
626 |
+
foreach ( $columns_in_post_table as $column ) {
|
627 |
+
array_push( $post_fields, $column->Field );
|
628 |
+
} // $post_fields containing the required names from the post table
|
629 |
+
foreach ( $all_custom_columns as $custom ) {
|
630 |
+
array_push( $custom_fields, $custom->attribute_name );
|
631 |
+
}
|
632 |
+
// $custom_fields containing the custom names
|
633 |
+
// filter the post columns, the meta columns and the custom columns to only those that are actually in use
|
634 |
+
|
635 |
+
foreach ( $active_field_names as $column ) {
|
636 |
+
if ( in_array( $column, $post_fields ) && 'ID' !== $column ) { // because ID is always required, it's excluded here and hard coded in the query
|
637 |
+
$post_columns_string .= $column . ', '; // here a string is required to push in the query
|
638 |
+
} elseif ( in_array( $column, $custom_fields ) ) {
|
639 |
+
array_push( $active_custom_fields, $column );
|
640 |
+
} elseif ( in_array( $column, $third_party_custom_fields ) ) {
|
641 |
+
array_push( $active_third_party_custom_fields, $column );
|
642 |
+
} else {
|
643 |
+
array_push( $meta_fields, $column );
|
644 |
+
}
|
645 |
+
}
|
646 |
+
|
647 |
+
return array(
|
648 |
+
'post_column_string' => $post_columns_string,
|
649 |
+
'meta_fields' => $meta_fields,
|
650 |
+
'active_custom_fields' => $active_custom_fields,
|
651 |
+
'third_party_custom_fields' => $third_party_custom_fields,
|
652 |
+
);
|
653 |
+
}
|
654 |
+
|
655 |
+
/**
|
656 |
+
* header text, override this function in the class-feed.php if required for a channel specific header
|
657 |
+
*
|
658 |
+
* @param string $title
|
659 |
+
*
|
660 |
+
* @return string
|
661 |
+
*/
|
662 |
+
protected function header( $title ) {
|
663 |
+
return apply_filters( 'tvc_xml_header', $title );
|
664 |
+
}
|
665 |
+
|
666 |
+
/**
|
667 |
+
* footer text, override if required for a channel specific footer
|
668 |
+
*
|
669 |
+
* @return string
|
670 |
+
*/
|
671 |
+
protected function footer() {
|
672 |
+
return apply_filters( 'tvc_xml_footer', '</products></rss>' );
|
673 |
+
}
|
674 |
+
}
|
675 |
+
// end of TVC_Feed_Master_Class
|
676 |
+
endif;
|
includes/application/class-tvc-email.php
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Email Class.
|
5 |
+
*
|
6 |
+
* @package Google Product Feed Manager/Application/Classes
|
7 |
+
* @version 1.2.0
|
8 |
+
* @since 2.3.0
|
9 |
+
*/
|
10 |
+
|
11 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
12 |
+
exit;
|
13 |
+
}
|
14 |
+
|
15 |
+
if ( ! class_exists( 'TVC_Email' ) ) :
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Email Class
|
19 |
+
*/
|
20 |
+
class TVC_Email {
|
21 |
+
|
22 |
+
public static function send_feed_failed_message() {
|
23 |
+
$to = get_option( 'tvc_notice_mailaddress' ) ? get_option( 'tvc_notice_mailaddress' ) : get_bloginfo( 'admin_email' );
|
24 |
+
|
25 |
+
if ( ! $to ) {
|
26 |
+
return false;
|
27 |
+
}
|
28 |
+
$header = self::feed_failed_header();
|
29 |
+
$message = self::feed_failed_message();
|
30 |
+
|
31 |
+
return self::send( $to, $header, $message );
|
32 |
+
}
|
33 |
+
|
34 |
+
private static function feed_failed_header() {
|
35 |
+
return sprintf( 'Feed generation failure on your %s shop', get_bloginfo( 'name' ) );
|
36 |
+
}
|
37 |
+
|
38 |
+
private static function feed_failed_message() {
|
39 |
+
$message = sprintf(
|
40 |
+
'This is an automatic message from your %s plugin. One or more product feeds on your %s shop failed to generate. Please check the status of your feeds and try to manually regenerate them again.
|
41 |
+
|
42 |
+
Should this problem persist, please open a support ticket.',
|
43 |
+
TVC_EDD_SL_ITEM_NAME,
|
44 |
+
get_bloginfo( 'name' )
|
45 |
+
);
|
46 |
+
|
47 |
+
return $message;
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Sends the email
|
52 |
+
*
|
53 |
+
* @param string $to to address
|
54 |
+
* @param string $subject the subject
|
55 |
+
* @param string $message the message
|
56 |
+
*
|
57 |
+
* @return bool whether the mail contents was send successfully
|
58 |
+
*/
|
59 |
+
private static function send( $to, $subject, $message ) {
|
60 |
+
if ( is_email( $to ) ) {
|
61 |
+
return (bool) wp_mail( $to, $subject, $message );
|
62 |
+
} else {
|
63 |
+
return false;
|
64 |
+
}
|
65 |
+
}
|
66 |
+
}
|
67 |
+
// end of TVC_Email class
|
68 |
+
endif;
|
includes/application/class-tvc-feed-controller.php
ADDED
@@ -0,0 +1,208 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Google Product Feed Controller Class.
|
5 |
+
*
|
6 |
+
* @package Google Product Feed Manager/Application/Classes
|
7 |
+
* @version 1.3.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Feed_Controller' ) ) :
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Feed Controller Class
|
18 |
+
*
|
19 |
+
* @since 1.10.0
|
20 |
+
*/
|
21 |
+
class TVC_Feed_Controller {
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Removes a feed id from the feed queue
|
25 |
+
*
|
26 |
+
* @param string $feed_id
|
27 |
+
*/
|
28 |
+
public static function remove_id_from_feed_queue( $feed_id ) {
|
29 |
+
$feed_queue = self::get_feed_queue();
|
30 |
+
$key = array_search( $feed_id, $feed_queue );
|
31 |
+
|
32 |
+
if ( false !== $key ) {
|
33 |
+
unset( $feed_queue[ $key ] );
|
34 |
+
$feed_queue = array_values( $feed_queue ); // resort after unset
|
35 |
+
update_site_option( 'tvc_feed_queue', $feed_queue );
|
36 |
+
|
37 |
+
if ( self::feed_queue_is_empty() ) {
|
38 |
+
tvc_clear_feed_process_data();
|
39 |
+
}
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Adds an feed id to the feed queue
|
45 |
+
*
|
46 |
+
* @param string $feed_id
|
47 |
+
*/
|
48 |
+
public static function add_id_to_feed_queue( $feed_id ) {
|
49 |
+
$feed_queue = self::get_feed_queue();
|
50 |
+
|
51 |
+
if ( ! in_array( $feed_id, $feed_queue ) ) {
|
52 |
+
array_push( $feed_queue, $feed_id );
|
53 |
+
update_site_option( 'tvc_feed_queue', $feed_queue );
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Gets the next feed id from the feed queue
|
59 |
+
*/
|
60 |
+
public static function get_next_id_from_feed_queue() {
|
61 |
+
$feed_queue = self::get_feed_queue();
|
62 |
+
|
63 |
+
return count( $feed_queue ) > 0 ? $feed_queue[0] : false;
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Empties the feed queue
|
68 |
+
*/
|
69 |
+
public static function clear_feed_queue() {
|
70 |
+
update_site_option( 'tvc_feed_queue', array() );
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Checks if the feed queue is empty
|
75 |
+
*
|
76 |
+
* @return bool
|
77 |
+
*/
|
78 |
+
public static function feed_queue_is_empty() {
|
79 |
+
$queue = self::get_feed_queue();
|
80 |
+
|
81 |
+
return ( count( $queue ) < 1 ) ? true : false;
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Returns the number of product ids that are still in the queue
|
86 |
+
*
|
87 |
+
* @since 2.3.0
|
88 |
+
* @return int number of product ids still in the queue
|
89 |
+
*/
|
90 |
+
public static function nr_ids_remaining_in_queue() {
|
91 |
+
$queue = self::get_feed_queue();
|
92 |
+
|
93 |
+
return count( $queue );
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* Sets the background_process_is_running option
|
98 |
+
*
|
99 |
+
* @param bool $set (default false)
|
100 |
+
*/
|
101 |
+
public static function set_feed_processing_flag( $set = false ) {
|
102 |
+
$status = false !== $set ? 'true' : 'false';
|
103 |
+
update_site_option( 'tvc_background_process_is_running', $status );
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Get the background_process_is_running status
|
108 |
+
*
|
109 |
+
* @return bool
|
110 |
+
*/
|
111 |
+
public static function feed_is_processing() {
|
112 |
+
$status = get_option( 'tvc_background_process_is_running', 'false' );
|
113 |
+
|
114 |
+
return 'true' === $status ? true : false;
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* Checks if a running feed size is still growing, in order to identify a failing feed process.
|
119 |
+
*
|
120 |
+
* @since 2.2.0
|
121 |
+
*
|
122 |
+
* @param string $feed_file String with the full path and name of the feed file.
|
123 |
+
*
|
124 |
+
* @return boolean False if the feed still grows, true if it stopped growing for a certain time.
|
125 |
+
*/
|
126 |
+
public static function feed_processing_failed( $feed_file ) {
|
127 |
+
|
128 |
+
if ( '' === $feed_file ) {
|
129 |
+
return null;
|
130 |
+
}
|
131 |
+
|
132 |
+
$trans = get_transient( 'tvc_feed_file_size' );
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Get the feed file name that's stored in the transient or take the $feed_file parameter.
|
136 |
+
*/
|
137 |
+
$trans_feed_file = $trans ? substr( $trans, strrpos( $trans, '|' ) + 1 ) : $feed_file;
|
138 |
+
|
139 |
+
/**
|
140 |
+
* if the transient was empty or the feed file in the transient is not the currently active file, reset the transient
|
141 |
+
*/
|
142 |
+
if ( false === $trans || $feed_file !== $trans_feed_file ) {
|
143 |
+
$trans = '0|0|' . $feed_file;
|
144 |
+
set_transient( 'tvc_feed_file_size', $trans, TVC_TRANSIENT_LIVE );
|
145 |
+
}
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Get the last data.
|
149 |
+
*/
|
150 |
+
$stored = explode( '|', $trans );
|
151 |
+
$prev_feed_size = $stored[0];
|
152 |
+
$prev_feed_time_stamp = $stored[1];
|
153 |
+
$feed_file = $trans_feed_file;
|
154 |
+
$curr_feed_size = file_exists( $feed_file ) ? filesize( $feed_file ) : false;
|
155 |
+
|
156 |
+
/**
|
157 |
+
* If file does not exist, return true.
|
158 |
+
*/
|
159 |
+
if ( false === $curr_feed_size ) {
|
160 |
+
delete_transient( 'tvc_feed_file_size' ); // reset the counter
|
161 |
+
return true;
|
162 |
+
}
|
163 |
+
|
164 |
+
// If the size of the feed has not grown.
|
165 |
+
if ( $curr_feed_size <= $prev_feed_size ) {
|
166 |
+
// And the delay time has passed.
|
167 |
+
if ( $prev_feed_time_stamp + apply_filters( 'tvc_delay_failed_label', TVC_DELAY_FAILED_LABEL, $feed_file ) < time() ) {
|
168 |
+
delete_transient( 'tvc_feed_file_size' ); // reset the counter
|
169 |
+
return true;
|
170 |
+
} else {
|
171 |
+
return false;
|
172 |
+
}
|
173 |
+
} else { // If the file size has increased, reset the timer and return false.
|
174 |
+
set_transient( 'tvc_feed_file_size', $curr_feed_size . '|' . time() . '|' . $feed_file, TVC_TRANSIENT_LIVE );
|
175 |
+
return false;
|
176 |
+
}
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Updates the timer that is used as reference to monitor if a file is growing during the feed production process.
|
181 |
+
*
|
182 |
+
* @since 2.11.0
|
183 |
+
*/
|
184 |
+
public static function update_file_grow_monitoring_timer() {
|
185 |
+
// Get the current monitor data.
|
186 |
+
$grow_monitor_array = get_transient( 'tvc_feed_file_size' );
|
187 |
+
|
188 |
+
if ( ! $grow_monitor_array ) { // The tvc_feed_file_size is not set in the non-background mode.
|
189 |
+
return;
|
190 |
+
}
|
191 |
+
|
192 |
+
$grow_monitor_data = explode( '|', $grow_monitor_array );
|
193 |
+
|
194 |
+
// Reset the timer part of the monitor.
|
195 |
+
set_transient( 'tvc_feed_file_size', $grow_monitor_data[0] . '|' . time() . '|' . $grow_monitor_data[2], TVC_TRANSIENT_LIVE );
|
196 |
+
}
|
197 |
+
|
198 |
+
/**
|
199 |
+
* Returns the current feed queue
|
200 |
+
*
|
201 |
+
* @return array with feed ids in the queue or an empty array
|
202 |
+
*/
|
203 |
+
protected static function get_feed_queue() {
|
204 |
+
return get_site_option( 'tvc_feed_queue', array() );
|
205 |
+
}
|
206 |
+
}
|
207 |
+
|
208 |
+
endif;
|
includes/application/class-tvc-feed-processor.php
ADDED
@@ -0,0 +1,341 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Google Product Feed Controller Class.
|
5 |
+
*
|
6 |
+
* @package Google Product Feed Manager/Application/Classes
|
7 |
+
* @version 1.5.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Feed_Processor' ) ) :
|
15 |
+
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Feed Processor Class
|
19 |
+
*
|
20 |
+
* @since 1.10.0
|
21 |
+
*/
|
22 |
+
class TVC_Feed_Processor extends TVC_Background_Process {
|
23 |
+
|
24 |
+
use TVC_Processing_Support;
|
25 |
+
use TVC_Feed_Processor_Functions;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Action identifier
|
29 |
+
*
|
30 |
+
* @var string
|
31 |
+
*/
|
32 |
+
protected $action = 'feed_generation_process';
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Path to the feed file
|
36 |
+
*
|
37 |
+
* @var string
|
38 |
+
*/
|
39 |
+
private $_feed_file_path;
|
40 |
+
|
41 |
+
/**
|
42 |
+
* General feed data
|
43 |
+
*
|
44 |
+
* @var stdClass
|
45 |
+
*/
|
46 |
+
private $_feed_data;
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Required pre feed generation data
|
50 |
+
*
|
51 |
+
* @var array
|
52 |
+
*/
|
53 |
+
private $_pre_data;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Contains the channel specific main category title and description title
|
57 |
+
*
|
58 |
+
* @var array
|
59 |
+
*/
|
60 |
+
private $_channel_details;
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Contains the relations between WooCommerce and channel fields
|
64 |
+
*
|
65 |
+
* @var array
|
66 |
+
*/
|
67 |
+
private $_relation_table;
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Placeholder for the correct channel class
|
71 |
+
*
|
72 |
+
* @var string
|
73 |
+
*/
|
74 |
+
private $_channel_class;
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Task
|
78 |
+
*
|
79 |
+
* Starts a single feed update task
|
80 |
+
*
|
81 |
+
* @param array product
|
82 |
+
* @param stdClass feed_data
|
83 |
+
* @param string feed_file_path
|
84 |
+
* @param array pre_data
|
85 |
+
* @param array channel_details
|
86 |
+
* @param array relation_table
|
87 |
+
*
|
88 |
+
* @return boolean
|
89 |
+
*/
|
90 |
+
protected function task( $task_data, $feed_data, $feed_file_path, $pre_data, $channel_details, $relation_table ) {
|
91 |
+
if ( ! $task_data ) {
|
92 |
+
return false;
|
93 |
+
}
|
94 |
+
|
95 |
+
$this->_feed_data = $feed_data;
|
96 |
+
$this->_feed_file_path = $feed_file_path;
|
97 |
+
$this->_pre_data = $pre_data;
|
98 |
+
$this->_channel_details = $channel_details;
|
99 |
+
$this->_relation_table = $relation_table;
|
100 |
+
|
101 |
+
if ( ! $this->_channel_details['channel_id'] ) {
|
102 |
+
return false;
|
103 |
+
}
|
104 |
+
|
105 |
+
// instantiate the correct channel class
|
106 |
+
$this->_channel_class = new TVC_Google_Feed_Class();
|
107 |
+
|
108 |
+
return $this->do_task( $task_data );
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Complete
|
113 |
+
*/
|
114 |
+
public function complete() {
|
115 |
+
parent::complete();
|
116 |
+
|
117 |
+
// remove the properties from the options table
|
118 |
+
$properties_key = get_site_option( 'tvc_background_process_key' );
|
119 |
+
delete_site_option( 'tvc_background_process_key' );
|
120 |
+
delete_site_option( 'file_path_' . $properties_key );
|
121 |
+
delete_site_option( 'feed_data_' . $properties_key );
|
122 |
+
delete_site_option( 'pre_data_' . $properties_key );
|
123 |
+
delete_site_option( 'channel_details_' . $properties_key );
|
124 |
+
delete_site_option( 'relations_table_' . $properties_key );
|
125 |
+
|
126 |
+
$feed_status = '0' !== $this->_feed_data->status && '3' !== $this->_feed_data->status && '4' !== $this->_feed_data->status ? $this->_feed_data->status : $this->_feed_data->baseStatusId;
|
127 |
+
$feed_title = $this->_feed_data->title . '.' . pathinfo( $this->_feed_file_path, PATHINFO_EXTENSION );
|
128 |
+
$this->register_feed_update( $this->_feed_data->feedId, $feed_title, count( $this->processed_products ), $feed_status );
|
129 |
+
$this->clear_the_queue();
|
130 |
+
|
131 |
+
// now the feed is ready to go, remove the feed id from the feed queue
|
132 |
+
TVC_Feed_Controller::remove_id_from_feed_queue( $this->_feed_data->feedId );
|
133 |
+
TVC_Feed_Controller::set_feed_processing_flag( false );
|
134 |
+
|
135 |
+
$message = sprintf( 'Completed feed %s. The feed should contain %d products and its status has been set to %s.', $this->_feed_data->feedId, count( $this->processed_products ), $feed_status );
|
136 |
+
do_action( 'tvc_feed_generation_message', $this->_feed_data->feedId, $message );
|
137 |
+
do_action( 'tvc_register_feed_url', $this->_feed_data->feedId, $this->_feed_data->url );
|
138 |
+
|
139 |
+
if ( ! TVC_Feed_Controller::feed_queue_is_empty() ) {
|
140 |
+
do_action( 'tvc_next_in_queue_feed_update_activated', $this->_feed_data->feedId );
|
141 |
+
|
142 |
+
// so there is another feed in the queue
|
143 |
+
$feed_master_class = new TVC_Feed_Master_Class( $this->_feed_data->feedId );
|
144 |
+
$feed_master_class->update_feed_file();
|
145 |
+
}
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Task action
|
150 |
+
* Selects the required action
|
151 |
+
*
|
152 |
+
* @param array $task_data
|
153 |
+
*
|
154 |
+
* @return boolean
|
155 |
+
*/
|
156 |
+
private function do_task( $task_data ) {
|
157 |
+
|
158 |
+
if ( array_key_exists( 'product_id', $task_data ) ) {
|
159 |
+
return $this->add_product_to_feed( $task_data['product_id'] );
|
160 |
+
} elseif ( array_key_exists( 'file_format_line', $task_data ) ) {
|
161 |
+
$task_data['file_format_line'] = str_replace( '<wf-connection-string>', '<link>', $task_data['file_format_line'] );
|
162 |
+
|
163 |
+
return $this->add_file_format_line_to_feed( $task_data );
|
164 |
+
} elseif ( array_key_exists( 'error_message', $task_data ) ) {
|
165 |
+
return $this->add_error_message_to_feed( $task_data );
|
166 |
+
} else {
|
167 |
+
return false;
|
168 |
+
}
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Ads a single product based on a product id to the feed file
|
173 |
+
*
|
174 |
+
* @param string $product_id
|
175 |
+
*
|
176 |
+
* @return boolean
|
177 |
+
*/
|
178 |
+
private function add_product_to_feed( $product_id ) {
|
179 |
+
if ( ! $product_id ) {
|
180 |
+
$message = 'Add product to feed process started without product id';
|
181 |
+
do_action( 'tvc_feed_generation_message', $this->_feed_data->feedId, $message );
|
182 |
+
|
183 |
+
return false;
|
184 |
+
}
|
185 |
+
|
186 |
+
$wc_product = wc_get_product( $product_id );
|
187 |
+
|
188 |
+
if ( false === $wc_product ) {
|
189 |
+
$message = sprintf( 'Failed to get the WooCommerce product data from product with id %s.', $product_id );
|
190 |
+
do_action( 'tvc_feed_generation_message', $this->_feed_data->feedId, $message );
|
191 |
+
|
192 |
+
return false;
|
193 |
+
}
|
194 |
+
|
195 |
+
do_action( 'tvc_started_product_processing', $this->_feed_data->feedId, $product_id );
|
196 |
+
|
197 |
+
$class_data = new TVC_Data();
|
198 |
+
|
199 |
+
$product_placeholder = array();
|
200 |
+
$post_columns_query_string = $this->_pre_data['database_fields']['post_column_string'] ? substr( $this->_pre_data['database_fields']['post_column_string'], 0, - 2 ) : '';
|
201 |
+
$product_parent_id = $product_id;
|
202 |
+
$product_data = (array) $this->get_products_main_data( $product_id, $wc_product->get_parent_id(), $post_columns_query_string );
|
203 |
+
|
204 |
+
/**
|
205 |
+
* Users can use the tvc_leave_links_in_descriptions filter if they want to keep links in the product descriptions by changing the
|
206 |
+
* filter output to true. They can also target specific feeds.
|
207 |
+
*
|
208 |
+
* @since 2.6.0
|
209 |
+
*/
|
210 |
+
if ( ! apply_filters( 'tvc_leave_links_in_descriptions', false, $this->_feed_data->feedId ) ) {
|
211 |
+
$this->remove_links_from_product_data_description( $product_data );
|
212 |
+
}
|
213 |
+
|
214 |
+
if ( ( $wc_product instanceof WC_Product_Variation && $this->_pre_data['include_vars'] )
|
215 |
+
|| ( $wc_product instanceof WC_Product_Variable ) && $this->_pre_data['include_vars'] ) {
|
216 |
+
|
217 |
+
$product_parent_id = $wc_product->get_parent_id();
|
218 |
+
|
219 |
+
// add parent data when this item is not available in the variation
|
220 |
+
if ( $post_columns_query_string ) {
|
221 |
+
$class_data->add_parent_data( $product_data, $product_parent_id, $post_columns_query_string );
|
222 |
+
}
|
223 |
+
|
224 |
+
$wpmr_variation_data = $class_data->get_own_variation_data( $product_id );
|
225 |
+
|
226 |
+
// get correct variation data
|
227 |
+
TVC_Variations::fill_product_data_with_variation_data( $product_data, $wc_product, $wpmr_variation_data, $this->_feed_data->language );
|
228 |
+
}
|
229 |
+
|
230 |
+
$row_category = $this->get_mapped_category( $product_parent_id, $this->_feed_data->mainCategory, json_decode( $this->_feed_data->categoryMapping ) );
|
231 |
+
|
232 |
+
if ( ! $row_category ) {
|
233 |
+
$message = sprintf( 'Could not identify the correct category map for product %s', $product_id );
|
234 |
+
do_action( 'tvc_feed_generation_message', $this->_feed_data->feedId, $message );
|
235 |
+
|
236 |
+
return false;
|
237 |
+
}
|
238 |
+
|
239 |
+
$row_filtered = $this->is_product_filtered( $this->_pre_data['filters'], $product_data );
|
240 |
+
|
241 |
+
// only process the product if its not filtered out
|
242 |
+
if ( ! $row_filtered ) {
|
243 |
+
// for each row loop through each field
|
244 |
+
foreach ( $this->_pre_data['active_fields'] as $field ) {
|
245 |
+
$field_meta_data = $this->get_meta_data_from_specific_field( $field, $this->_feed_data->attributes );
|
246 |
+
|
247 |
+
// get the field data based on the user settings
|
248 |
+
$feed_object = $this->process_product_field(
|
249 |
+
$product_data,
|
250 |
+
$field_meta_data,
|
251 |
+
$this->_channel_details['category_name'],
|
252 |
+
$row_category,
|
253 |
+
$this->_feed_data->language,
|
254 |
+
$this->_relation_table
|
255 |
+
);
|
256 |
+
|
257 |
+
$key = key( $feed_object );
|
258 |
+
|
259 |
+
// for an xml file only add fields that contain data
|
260 |
+
if ( ( ! empty( $feed_object[ $key ] ) || '0' === $feed_object[ $key ] ) || 'xml' !== pathinfo( $this->_feed_file_path, PATHINFO_EXTENSION ) ) {
|
261 |
+
|
262 |
+
// catch the DraftImages key for the Ricardo.ch channel
|
263 |
+
if ( 'DraftImages' !== $key ) {
|
264 |
+
$product_placeholder[ $key ] = $feed_object[ $key ];
|
265 |
+
} else {
|
266 |
+
$support_class = new TVC_Feed_Support();
|
267 |
+
$support_class->process_ricardo_draftimages( $product_placeholder, $feed_object[ $key ] );
|
268 |
+
}
|
269 |
+
}
|
270 |
+
}
|
271 |
+
} else {
|
272 |
+
$message = sprintf( 'Product %s is filtered out', $product_id );
|
273 |
+
do_action( 'tvc_feed_generation_message', $this->_feed_data->feedId, $message );
|
274 |
+
|
275 |
+
return 'filtered';
|
276 |
+
}
|
277 |
+
|
278 |
+
if ( $product_placeholder ) {
|
279 |
+
// The tvc_feed_item_value filter allows users to modify the data that goes into the feed. The $data variable contains an array
|
280 |
+
// with all the data that goes into the feed, with the items name as key
|
281 |
+
$product_placeholder = apply_filters( 'tvc_feed_item_value', $product_placeholder, $this->_feed_data->feedId, $product_id );
|
282 |
+
|
283 |
+
return $this->write_product_object( $product_placeholder, $this->_feed_data->feedId, $product_id );
|
284 |
+
} else {
|
285 |
+
return false;
|
286 |
+
}
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* Appends a product to the feed
|
291 |
+
*
|
292 |
+
* @param array $feed_product_object
|
293 |
+
* @param string $feed_id
|
294 |
+
* @param string $product_id
|
295 |
+
*
|
296 |
+
* @return string product added or boolean false
|
297 |
+
*/
|
298 |
+
private function write_product_object( $feed_product_object, $feed_id, $product_id ) {
|
299 |
+
/**
|
300 |
+
* @since 2.3.0
|
301 |
+
*/
|
302 |
+
do_action( 'tvc_add_product_to_feed', $feed_id, $product_id );
|
303 |
+
|
304 |
+
$product_text = $this->generate_feed_text( $feed_product_object );
|
305 |
+
|
306 |
+
if ( false === file_put_contents( $this->_feed_file_path, $product_text, FILE_APPEND ) ) {
|
307 |
+
tvc_write_log_file( sprintf( 'Could not write product %s to the feed', $product_id ) );
|
308 |
+
|
309 |
+
return false;
|
310 |
+
} else {
|
311 |
+
return 'product added';
|
312 |
+
}
|
313 |
+
}
|
314 |
+
|
315 |
+
/**
|
316 |
+
* convert the feed data of a single product into xml or csv text depending on the channel
|
317 |
+
*
|
318 |
+
* @param array $data
|
319 |
+
*
|
320 |
+
* @return string
|
321 |
+
*/
|
322 |
+
protected function generate_feed_text( $data ) {
|
323 |
+
switch ( pathinfo( $this->_feed_file_path, PATHINFO_EXTENSION ) ) {
|
324 |
+
case 'xml':
|
325 |
+
return $this->convert_data_to_xml( $data, $this->_channel_details['category_name'], $this->_channel_details['description_name'], $this->_channel_details['channel_id'] );
|
326 |
+
|
327 |
+
case 'txt':
|
328 |
+
return $this->convert_data_to_txt( $data );
|
329 |
+
|
330 |
+
case 'csv':
|
331 |
+
$csv_sep = apply_filters( 'tvc_csv_separator', get_correct_csv_separator( $this->_channel_details['channel_id'] ) );
|
332 |
+
|
333 |
+
return $this->convert_data_to_csv( $data, $this->_pre_data['active_fields'], $csv_sep );
|
334 |
+
|
335 |
+
case 'tsv':
|
336 |
+
return $this->convert_data_to_tsv( $data );
|
337 |
+
}
|
338 |
+
return '';
|
339 |
+
}
|
340 |
+
}
|
341 |
+
endif;
|
includes/application/class-tvc-feed-queries.php
ADDED
@@ -0,0 +1,243 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Google Feed Queries Class.
|
5 |
+
*
|
6 |
+
* @package Google Product Feed Manager/Application/Classes
|
7 |
+
* @version 2.1.1
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Feed_Queries' ) ) :
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Feed Queries Class
|
18 |
+
*/
|
19 |
+
class TVC_Feed_Queries {
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @param $query
|
23 |
+
* @param $value
|
24 |
+
* @return bool
|
25 |
+
*/
|
26 |
+
public function includes_query( $query, $value ) {
|
27 |
+
return $query[3] && strpos( strtolower( $value ), strtolower( trim( $query[3] ) ) ) !== false ? false : true;
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @param $query
|
32 |
+
* @param $value
|
33 |
+
* @return bool
|
34 |
+
*/
|
35 |
+
public function does_not_include_query( $query, $value ) {
|
36 |
+
return $query[3] && strpos( strtolower( $value ), strtolower( trim( $query[3] ) ) ) === false ? false : true;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @param $query
|
41 |
+
* @param $value
|
42 |
+
* @return bool
|
43 |
+
*/
|
44 |
+
public function is_equal_to_query( $query, $value ) {
|
45 |
+
return strtolower( $value ) === strtolower( trim( $query[3] ) ) ? false : true;
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @param $query
|
50 |
+
* @param $value
|
51 |
+
* @return bool
|
52 |
+
*/
|
53 |
+
public function is_not_equal_to_query( $query, $value ) {
|
54 |
+
return strtolower( $value ) !== strtolower( trim( $query[3] ) ) ? false : true;
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @param $value
|
59 |
+
* @return bool
|
60 |
+
*/
|
61 |
+
public function is_empty( $value ) {
|
62 |
+
if ( ! is_array( $value ) ) {
|
63 |
+
$value = trim( $value );
|
64 |
+
}
|
65 |
+
|
66 |
+
return empty( $value ) ? false : true;
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @param $value
|
71 |
+
* @return bool
|
72 |
+
*/
|
73 |
+
public function is_not_empty_query( $value ) {
|
74 |
+
if ( ! is_array( $value ) ) {
|
75 |
+
$value = trim( $value );
|
76 |
+
}
|
77 |
+
|
78 |
+
return ! empty( $value ) ? false : true;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* @param $query
|
83 |
+
* @param $value
|
84 |
+
* @return bool
|
85 |
+
*/
|
86 |
+
public function starts_with_query( $query, $value ) {
|
87 |
+
if ( ! empty( $value ) && strrpos( strtolower( $value ), strtolower( trim( $query[3] ) ), - strlen( $value ) ) !== false ) {
|
88 |
+
return false;
|
89 |
+
} else {
|
90 |
+
return true;
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* @param $query
|
96 |
+
* @param $value
|
97 |
+
* @return bool
|
98 |
+
*/
|
99 |
+
public function does_not_start_with_query( $query, $value ) {
|
100 |
+
if ( empty( $value ) || strrpos( strtolower( $value ), strtolower( trim( $query[3] ) ), - strlen( $value ) ) === false ) {
|
101 |
+
return false;
|
102 |
+
} else {
|
103 |
+
return true;
|
104 |
+
}
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* @param $query
|
109 |
+
* @param $value
|
110 |
+
* @return bool
|
111 |
+
*/
|
112 |
+
public function ends_with_query( $query, $value ) {
|
113 |
+
$search_string = trim( $query[3] );
|
114 |
+
$value_length = strlen( $value );
|
115 |
+
|
116 |
+
if ( ! empty( $value ) && ( $value_length - strlen( $search_string ) ) >= 0 && strpos( $value, $search_string, $value_length ) !== false ) {
|
117 |
+
return false;
|
118 |
+
} else {
|
119 |
+
return true;
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* @param $query
|
125 |
+
* @param $value
|
126 |
+
* @return bool
|
127 |
+
*/
|
128 |
+
public function does_not_end_with_query( $query, $value ) {
|
129 |
+
$search_string = trim( $query[3] );
|
130 |
+
$value_length = strlen( $value );
|
131 |
+
|
132 |
+
if ( ! empty( $value ) && ( $value_length - strlen( $search_string ) ) >= 0 && strpos( $value, $search_string, $value_length ) !== false ) {
|
133 |
+
return true;
|
134 |
+
} else {
|
135 |
+
return false;
|
136 |
+
}
|
137 |
+
}
|
138 |
+
|
139 |
+
/**
|
140 |
+
* @param $query
|
141 |
+
* @param $value
|
142 |
+
* @return bool
|
143 |
+
*/
|
144 |
+
public function is_greater_than_query( $query, $value ) {
|
145 |
+
$data_nr = $this->convert_to_us_notation( trim( $value ) );
|
146 |
+
$condition_nr = $this->convert_to_us_notation( trim( $query[3] ) );
|
147 |
+
|
148 |
+
if ( is_numeric( $data_nr ) && is_numeric( $condition_nr ) ) {
|
149 |
+
return (float) $data_nr > (float) $condition_nr ? false : true;
|
150 |
+
} else {
|
151 |
+
return false;
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* @param $query
|
157 |
+
* @param $value
|
158 |
+
* @return bool
|
159 |
+
*/
|
160 |
+
public function is_greater_or_equal_to_query( $query, $value ) {
|
161 |
+
$data_nr = $this->convert_to_us_notation( trim( $value ) );
|
162 |
+
$condition_nr = $this->convert_to_us_notation( trim( $query[3] ) );
|
163 |
+
|
164 |
+
if ( is_numeric( $data_nr ) && is_numeric( trim( $condition_nr ) ) ) {
|
165 |
+
return (float) $data_nr >= (float) $condition_nr ? false : true;
|
166 |
+
} else {
|
167 |
+
return false;
|
168 |
+
}
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* @param $query
|
173 |
+
* @param $value
|
174 |
+
* @return bool
|
175 |
+
*/
|
176 |
+
public function is_smaller_than_query( $query, $value ) {
|
177 |
+
$data_nr = $this->convert_to_us_notation( trim( $value ) );
|
178 |
+
$condition_nr = $this->convert_to_us_notation( trim( $query[3] ) );
|
179 |
+
|
180 |
+
if ( is_numeric( $data_nr ) && is_numeric( $condition_nr ) ) {
|
181 |
+
return (float) $data_nr < (float) $condition_nr ? false : true;
|
182 |
+
} else {
|
183 |
+
return false;
|
184 |
+
}
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* @param $query
|
189 |
+
* @param $value
|
190 |
+
* @return bool
|
191 |
+
*/
|
192 |
+
public function is_smaller_or_equal_to_query( $query, $value ) {
|
193 |
+
$data_nr = $this->convert_to_us_notation( trim( $value ) );
|
194 |
+
$condition_nr = $this->convert_to_us_notation( trim( $query[3] ) );
|
195 |
+
|
196 |
+
if ( is_numeric( $data_nr ) && is_numeric( $condition_nr ) ) {
|
197 |
+
return (float) $data_nr <= (float) $condition_nr ? false : true;
|
198 |
+
} else {
|
199 |
+
return false;
|
200 |
+
}
|
201 |
+
}
|
202 |
+
|
203 |
+
/**
|
204 |
+
* @param $query
|
205 |
+
* @param $value
|
206 |
+
* @return bool
|
207 |
+
*/
|
208 |
+
public function is_between_query( $query, $value ) {
|
209 |
+
$data_nr = $this->convert_to_us_notation( trim( $value ) );
|
210 |
+
$condition_nr_low = $this->convert_to_us_notation( trim( $query[3] ) );
|
211 |
+
$condition_nr_high = $this->convert_to_us_notation( trim( $query[5] ) );
|
212 |
+
|
213 |
+
if ( is_numeric( $data_nr ) && is_numeric( $condition_nr_low ) && is_numeric( $condition_nr_high ) ) {
|
214 |
+
if ( (float) $data_nr > (float) $condition_nr_low && (float) $data_nr < (float) $condition_nr_high ) {
|
215 |
+
return false;
|
216 |
+
} else {
|
217 |
+
return true;
|
218 |
+
}
|
219 |
+
} else {
|
220 |
+
return false;
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* @param $current_value
|
226 |
+
* @return mixed
|
227 |
+
*/
|
228 |
+
private function convert_to_us_notation( $current_value ) {
|
229 |
+
$decimal_sep = get_option( 'woocommerce_price_decimal_sep' );
|
230 |
+
$thousands_sep = get_option( 'woocommerce_price_thousand_sep' );
|
231 |
+
|
232 |
+
if ( ! preg_match( '/[a-zA-Z]/', $current_value ) ) { // only remove the commas if the current value has no letters
|
233 |
+
$no_thousands_sep = str_replace( $thousands_sep, '', $current_value );
|
234 |
+
|
235 |
+
return ',' === $decimal_sep ? str_replace( ',', '.', $no_thousands_sep ) : $no_thousands_sep;
|
236 |
+
} else {
|
237 |
+
return $current_value;
|
238 |
+
}
|
239 |
+
}
|
240 |
+
}
|
241 |
+
// end of TVC_Feed_Queries_Class
|
242 |
+
|
243 |
+
endif;
|
includes/application/class-tvc-feed-support.php
ADDED
@@ -0,0 +1,301 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Product Feed Support Class.
|
5 |
+
*
|
6 |
+
* @package TVC Product Feed Manager/Application/Classes
|
7 |
+
* @version 1.1.2
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Feed_Support' ) ) :
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Feed Support Class
|
18 |
+
*/
|
19 |
+
class TVC_Feed_Support {
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @param $query_object
|
23 |
+
* @return bool|mixed
|
24 |
+
*/
|
25 |
+
public function get_query_string_from_query_object( $query_object ) {
|
26 |
+
// TODO: There's probably a better way to do this!
|
27 |
+
foreach ( $query_object as $value ) {
|
28 |
+
return $value;
|
29 |
+
}
|
30 |
+
|
31 |
+
return false;
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @param $feed_name
|
36 |
+
* @param $relations_table
|
37 |
+
* @return mixed|string
|
38 |
+
*/
|
39 |
+
public function find_relation( $feed_name, $relations_table ) {
|
40 |
+
$result = '';
|
41 |
+
|
42 |
+
foreach ( $relations_table as $relation ) {
|
43 |
+
if ( $relation['field'] === $feed_name ) {
|
44 |
+
$result = $relation['db'];
|
45 |
+
break;
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
$relations_table = null;
|
50 |
+
|
51 |
+
return $result;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* @param $term_id
|
56 |
+
* @param $category_mapping
|
57 |
+
* @return bool|int
|
58 |
+
*/
|
59 |
+
public function category_is_selected( $term_id, $category_mapping ) {
|
60 |
+
for ( $i = 0; $i < count( $category_mapping ); $i ++ ) {
|
61 |
+
if ( (string) $term_id === $category_mapping[ $i ]->shopCategoryId ) {
|
62 |
+
return $i;
|
63 |
+
}
|
64 |
+
}
|
65 |
+
return false;
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* @param $query_split
|
70 |
+
* @param $product_data
|
71 |
+
* @return bool
|
72 |
+
*/
|
73 |
+
public function check_query_result_on_specific_row( $query_split, $product_data ) {
|
74 |
+
$queries_class = new TVC_Feed_Queries;
|
75 |
+
$current_data = key_exists( $query_split[1], $product_data ) ? $product_data[ $query_split[1] ] : '';
|
76 |
+
|
77 |
+
// the following attributes can or will contain an array so surpress the type warning for these attributes
|
78 |
+
$suppress_type_warning_attributes = apply_filters(
|
79 |
+
'tvc_suppress_type_warning_attributes',
|
80 |
+
array(
|
81 |
+
'_wp_attachement_metadata',
|
82 |
+
)
|
83 |
+
);
|
84 |
+
|
85 |
+
if ( is_array( $current_data ) && ! in_array( $query_split[1], $suppress_type_warning_attributes ) ) { // A user had this once where he had an attribute that only showed "Array()" as value
|
86 |
+
$product_id = key_exists( 'ID', $product_data ) ? $product_data['ID'] : 'unknown';
|
87 |
+
$product_title = key_exists( 'post_title', $product_data ) ? $product_data['post_title'] : 'unknown';
|
88 |
+
|
89 |
+
$error_message = "There is something wrong with the '" . $query_split[1] . "' attribute of product '$product_title' with id $product_id. It seems to be of a wrong type.";
|
90 |
+
|
91 |
+
tvc_write_log_file( $error_message, 'debug' );
|
92 |
+
|
93 |
+
$current_data = $current_data[0];
|
94 |
+
}
|
95 |
+
|
96 |
+
$result = true;
|
97 |
+
|
98 |
+
switch ( $query_split[2] ) {
|
99 |
+
case 0: // includes
|
100 |
+
$result = $queries_class->includes_query( $query_split, $current_data );
|
101 |
+
break;
|
102 |
+
|
103 |
+
case 1: // does not include
|
104 |
+
$result = $queries_class->does_not_include_query( $query_split, $current_data );
|
105 |
+
break;
|
106 |
+
|
107 |
+
case 2: // is equal to
|
108 |
+
$result = $queries_class->is_equal_to_query( $query_split, $current_data );
|
109 |
+
break;
|
110 |
+
|
111 |
+
case 3: // is not equal to
|
112 |
+
$result = $queries_class->is_not_equal_to_query( $query_split, $current_data );
|
113 |
+
break;
|
114 |
+
|
115 |
+
case 4: // is empty
|
116 |
+
$result = $queries_class->is_empty( $current_data );
|
117 |
+
break;
|
118 |
+
|
119 |
+
case 5: // is not empty
|
120 |
+
$result = $queries_class->is_not_empty_query( $current_data );
|
121 |
+
break;
|
122 |
+
|
123 |
+
case 6: // starts with
|
124 |
+
$result = $queries_class->starts_with_query( $query_split, $current_data );
|
125 |
+
break;
|
126 |
+
|
127 |
+
case 7: // does not start with
|
128 |
+
$result = $queries_class->does_not_start_with_query( $query_split, $current_data );
|
129 |
+
break;
|
130 |
+
|
131 |
+
case 8: // ends with
|
132 |
+
$result = $queries_class->ends_with_query( $query_split, $current_data );
|
133 |
+
break;
|
134 |
+
|
135 |
+
case 9: // does not end with
|
136 |
+
$result = $queries_class->does_not_end_with_query( $query_split, $current_data );
|
137 |
+
break;
|
138 |
+
|
139 |
+
case 10: // is greater than
|
140 |
+
$result = $queries_class->is_greater_than_query( $query_split, $current_data );
|
141 |
+
break;
|
142 |
+
|
143 |
+
case 11: // is greater or equal to
|
144 |
+
$result = $queries_class->is_greater_or_equal_to_query( $query_split, $current_data );
|
145 |
+
break;
|
146 |
+
|
147 |
+
case 12: // is smaller than
|
148 |
+
$result = $queries_class->is_smaller_than_query( $query_split, $current_data );
|
149 |
+
break;
|
150 |
+
|
151 |
+
case 13: // is smaller or equal to
|
152 |
+
$result = $queries_class->is_smaller_or_equal_to_query( $query_split, $current_data );
|
153 |
+
break;
|
154 |
+
|
155 |
+
case 14: // is between
|
156 |
+
$result = $queries_class->is_between_query( $query_split, $current_data );
|
157 |
+
break;
|
158 |
+
|
159 |
+
default:
|
160 |
+
break;
|
161 |
+
}
|
162 |
+
|
163 |
+
return $result;
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* @param $current_value
|
168 |
+
* @param $edit_string
|
169 |
+
* @param $combination_string
|
170 |
+
* @param $combined_data_elements
|
171 |
+
* @param $feed_language
|
172 |
+
* @return float|int|mixed|string
|
173 |
+
*/
|
174 |
+
public function edit_value( $current_value, $edit_string, $combination_string, $combined_data_elements, $feed_language ) {
|
175 |
+
$value_editors = new TVC_Feed_Value_Editors;
|
176 |
+
|
177 |
+
$query_split = explode( '#', $edit_string );
|
178 |
+
|
179 |
+
switch ( $query_split[1] ) {
|
180 |
+
case 'change nothing':
|
181 |
+
$result = $current_value;
|
182 |
+
break;
|
183 |
+
|
184 |
+
case 'overwrite':
|
185 |
+
$result = $value_editors->overwrite_value( $query_split );
|
186 |
+
break;
|
187 |
+
|
188 |
+
case 'replace':
|
189 |
+
$result = $value_editors->replace_value( $query_split, $current_value );
|
190 |
+
break;
|
191 |
+
|
192 |
+
case 'remove':
|
193 |
+
$result = $value_editors->remove_value( $query_split, $current_value );
|
194 |
+
break;
|
195 |
+
|
196 |
+
case 'add prefix':
|
197 |
+
$result = $value_editors->add_prefix_value( $query_split, $current_value );
|
198 |
+
break;
|
199 |
+
|
200 |
+
case 'add suffix':
|
201 |
+
$result = $value_editors->add_suffix_value( $query_split, $current_value );
|
202 |
+
break;
|
203 |
+
|
204 |
+
case 'recalculate':
|
205 |
+
$result = $value_editors->recalculate_value( $query_split, $current_value, $combination_string, $combined_data_elements, $feed_language );
|
206 |
+
break;
|
207 |
+
|
208 |
+
case 'convert to child-element':
|
209 |
+
$result = $value_editors->convert_to_element( $query_split, $current_value );
|
210 |
+
break;
|
211 |
+
|
212 |
+
default:
|
213 |
+
$result = false;
|
214 |
+
break;
|
215 |
+
}
|
216 |
+
|
217 |
+
return $result;
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* @param $feed_filter_array
|
222 |
+
* @return array
|
223 |
+
*/
|
224 |
+
public function get_column_names_from_feed_filter_array( $feed_filter_array ) {
|
225 |
+
$empty_array = array();
|
226 |
+
$filters = $feed_filter_array ? json_decode( $feed_filter_array[0]['meta_value'] ) : $empty_array;
|
227 |
+
$column_names = array();
|
228 |
+
|
229 |
+
foreach ( $filters as $filter ) {
|
230 |
+
$query_string = $this->get_query_string_from_query_object( $filter );
|
231 |
+
$query_parts = explode( '#', $query_string );
|
232 |
+
|
233 |
+
array_push( $column_names, $query_parts[1] );
|
234 |
+
}
|
235 |
+
|
236 |
+
return $column_names;
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* makes a unique feed for a copy of an existing feed
|
241 |
+
*
|
242 |
+
* @param string $current_feed_name
|
243 |
+
*
|
244 |
+
* @return string
|
245 |
+
*/
|
246 |
+
public function next_unique_feed_name( $current_feed_name ) {
|
247 |
+
$queries_class = new TVC_Queries();
|
248 |
+
|
249 |
+
$title_end = explode( '_', $current_feed_name );
|
250 |
+
$end_nr = end( $title_end );
|
251 |
+
|
252 |
+
if ( count( $title_end ) > 1 && is_numeric( $end_nr ) ) {
|
253 |
+
$new_title = substr_replace( $current_feed_name, ( $end_nr + 1 ), - strlen( $end_nr ) );
|
254 |
+
} else {
|
255 |
+
$new_title = $current_feed_name . '_1';
|
256 |
+
$end_nr = '1';
|
257 |
+
}
|
258 |
+
|
259 |
+
// increase the end number of the title already exists
|
260 |
+
while ( $queries_class->title_exists( $new_title ) ) {
|
261 |
+
$new_title = substr_replace( $new_title, ( $end_nr + 1 ), - strlen( $end_nr ) );
|
262 |
+
$end_nr ++;
|
263 |
+
}
|
264 |
+
|
265 |
+
return $new_title;
|
266 |
+
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* Adds multiple single draft image urls to the product, specific for the Ricardo.ch channel
|
270 |
+
*
|
271 |
+
* @since 1.9.0
|
272 |
+
*
|
273 |
+
* @param array $product
|
274 |
+
* @param array $images
|
275 |
+
*/
|
276 |
+
public function process_ricardo_draftimages( &$product, $images ) {
|
277 |
+
for ( $i = 0; $i < 10; $i ++ ) {
|
278 |
+
$product["DraftImages[$i]"] = isset( $images[ $i ] ) ? $images[ $i ] : '';
|
279 |
+
}
|
280 |
+
}
|
281 |
+
|
282 |
+
/**
|
283 |
+
* Corrects issues where the active list is not the same as the data keys
|
284 |
+
*
|
285 |
+
* @since 1.9.0
|
286 |
+
*
|
287 |
+
* @param array $active_fields
|
288 |
+
*/
|
289 |
+
public function correct_active_fields_list( &$active_fields ) {
|
290 |
+
// correct for draft images in Ricardo.ch feed
|
291 |
+
if ( ( $key = array_search( 'DraftImages', $active_fields ) ) !== false ) {
|
292 |
+
unset( $active_fields[ $key ] );
|
293 |
+
for ( $i = 0; $i < 10; $i ++ ) {
|
294 |
+
array_push( $active_fields, "DraftImages[$i]" );
|
295 |
+
}
|
296 |
+
}
|
297 |
+
}
|
298 |
+
}
|
299 |
+
|
300 |
+
// end of TVC_Feed_Support
|
301 |
+
endif;
|
includes/application/class-tvc-feed-value-editors.php
ADDED
@@ -0,0 +1,240 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Product Feed Value Editors Class.
|
5 |
+
*
|
6 |
+
* @package TVC Product Feed Manager/Application/Classes
|
7 |
+
* @version 1.6.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
|
15 |
+
if ( ! class_exists( 'TVC_Feed_Value_Editors' ) ) :
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Feed Value Editors Class
|
19 |
+
*/
|
20 |
+
class TVC_Feed_Value_Editors {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @param $condition
|
24 |
+
* @return mixed
|
25 |
+
*/
|
26 |
+
public function overwrite_value( $condition ) {
|
27 |
+
return $condition[2];
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @param $condition
|
32 |
+
* @param $current_value
|
33 |
+
* @return mixed
|
34 |
+
*/
|
35 |
+
public function replace_value( $condition, $current_value ) {
|
36 |
+
return str_replace( $condition[2], $condition[3], $current_value );
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* @param $element_name
|
41 |
+
* @param $current_value
|
42 |
+
* @return string
|
43 |
+
*/
|
44 |
+
public function convert_to_element( $element_name, $current_value ) {
|
45 |
+
return "!sub:$element_name[2]|$current_value";
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @param $condition
|
50 |
+
* @param $current_value
|
51 |
+
* @return mixed
|
52 |
+
*/
|
53 |
+
public function remove_value( $condition, $current_value ) {
|
54 |
+
return str_replace( $condition[2], '', $current_value );
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @param $condition
|
59 |
+
* @param $current_value
|
60 |
+
* @return string
|
61 |
+
*/
|
62 |
+
public function add_prefix_value( $condition, $current_value ) {
|
63 |
+
return $condition[2] . $current_value;
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
* @param $condition
|
68 |
+
* @param $current_value
|
69 |
+
* @return string
|
70 |
+
*/
|
71 |
+
public function add_suffix_value( $condition, $current_value ) {
|
72 |
+
return $current_value . $condition[2];
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* @param $condition
|
77 |
+
* @param $current_value
|
78 |
+
* @param $combination_string
|
79 |
+
* @param $combined_data_elements
|
80 |
+
* @param $feed_language
|
81 |
+
* @return float|int|mixed|string
|
82 |
+
*/
|
83 |
+
public function recalculate_value( $condition, $current_value, $combination_string, $combined_data_elements, $feed_language ) {
|
84 |
+
if ( ! $combination_string ) {
|
85 |
+
$values = $this->make_recalculate_inputs( $current_value, $condition[3] );
|
86 |
+
$calculated_value = $this->recalculate( $condition[2], floatval( $values['main_val'] ), floatval( $values['sub_val'] ) );
|
87 |
+
|
88 |
+
return $this->is_money_value( $current_value ) ? tvc_prep_money_values( $calculated_value, $feed_language ) : $calculated_value;
|
89 |
+
|
90 |
+
} else {
|
91 |
+
if ( count( $combined_data_elements ) > 1 ) {
|
92 |
+
$combined_string_values = array();
|
93 |
+
|
94 |
+
foreach ( $combined_data_elements as $element ) {
|
95 |
+
$values = $this->make_recalculate_inputs( $element, $condition[3] );
|
96 |
+
|
97 |
+
$reg_match = '/[0-9.,]/'; // only numbers and decimals
|
98 |
+
|
99 |
+
$calculated_value = preg_match( $reg_match, $values['main_val'] ) && preg_match( $reg_match, $values['sub_val'] ) ?
|
100 |
+
$this->recalculate( $condition[2], floatval( $values['main_val'] ), floatval( $values['sub_val'] ) ) : $values['main_val'];
|
101 |
+
|
102 |
+
$end_value = $this->is_money_value( $element ) ? tvc_prep_money_values( $calculated_value, $feed_language ) : $calculated_value;
|
103 |
+
|
104 |
+
array_push( $combined_string_values, $end_value );
|
105 |
+
}
|
106 |
+
|
107 |
+
return $this->make_combined_result_string( $combined_string_values, $combination_string );
|
108 |
+
} else {
|
109 |
+
return '';
|
110 |
+
}
|
111 |
+
}
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* @param $values
|
116 |
+
* @param $combination_string
|
117 |
+
* @return mixed|string
|
118 |
+
*/
|
119 |
+
private function make_combined_result_string( $values, $combination_string ) {
|
120 |
+
$separators = $this->combination_separators();
|
121 |
+
$result_string = $values[0];
|
122 |
+
|
123 |
+
$combinations = explode( '|', $combination_string );
|
124 |
+
|
125 |
+
for ( $i = 1; $i < count( $combinations ); $i ++ ) {
|
126 |
+
$sep = explode( '#', $combinations[ $i ] );
|
127 |
+
$result_string .= $separators[ (int) $sep[0] ];
|
128 |
+
$result_string .= $values[ $i ];
|
129 |
+
}
|
130 |
+
return $result_string;
|
131 |
+
}
|
132 |
+
|
133 |
+
public function combination_separators() {
|
134 |
+
return array(
|
135 |
+
'',
|
136 |
+
' ',
|
137 |
+
', ',
|
138 |
+
'.',
|
139 |
+
'; ',
|
140 |
+
':',
|
141 |
+
'-',
|
142 |
+
'/',
|
143 |
+
'\\',
|
144 |
+
'||',
|
145 |
+
'_',
|
146 |
+
); // should correspond with tvc_getCombinedSeparatorList()
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* @param $current_value
|
151 |
+
* @param $current_sub_value
|
152 |
+
* @return array
|
153 |
+
*/
|
154 |
+
private function make_recalculate_inputs( $current_value, $current_sub_value ) {
|
155 |
+
if ( ! preg_match( '/[a-zA-Z]/', $current_value ) ) { // only remove the commas if the current value has no letters
|
156 |
+
$main_value = tvc_number_format_parse( $current_value );
|
157 |
+
} else {
|
158 |
+
$main_value = $current_value;
|
159 |
+
}
|
160 |
+
|
161 |
+
$sub_value = tvc_number_format_parse( $current_sub_value );
|
162 |
+
|
163 |
+
return array(
|
164 |
+
'main_val' => $main_value,
|
165 |
+
'sub_val' => $sub_value,
|
166 |
+
);
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* @param $meta_data
|
171 |
+
* @param $feed_language
|
172 |
+
* @return string
|
173 |
+
*/
|
174 |
+
public function prep_meta_values( $meta_data, $feed_language ) {
|
175 |
+
$result = $meta_data->meta_value;
|
176 |
+
|
177 |
+
if ( tvc_meta_key_is_money( $meta_data->meta_key ) ) {
|
178 |
+
$result = tvc_prep_money_values( $result, $feed_language );
|
179 |
+
}
|
180 |
+
|
181 |
+
return is_string( $result ) ? trim( $result ) : $result;
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Checks is a certain value could be a money value or not
|
186 |
+
*
|
187 |
+
* @param int or string $value
|
188 |
+
*
|
189 |
+
* @return boolean true if it is a money value
|
190 |
+
*/
|
191 |
+
public function is_money_value( $value ) {
|
192 |
+
// replace a comma separator with a period so it can be recognized as numeric
|
193 |
+
$possible_number = tvc_number_format_parse( $value );
|
194 |
+
|
195 |
+
// if its not a number it cannot be a money value
|
196 |
+
if ( ! is_numeric( $possible_number ) ) {
|
197 |
+
return false;
|
198 |
+
}
|
199 |
+
|
200 |
+
$last_pos = strrpos( (string) $value, get_option( 'woocommerce_price_decimal_sep' ) );
|
201 |
+
$value_length = strlen( (string) $value );
|
202 |
+
|
203 |
+
$actual_decimals = $value_length - $last_pos - 1;
|
204 |
+
|
205 |
+
return absint( get_option( 'woocommerce_price_num_decimals', 2 ) ) === $actual_decimals ? true : false;
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* @param $math
|
210 |
+
* @param $main_value
|
211 |
+
* @param $sub_value
|
212 |
+
* @return float|int|string
|
213 |
+
*/
|
214 |
+
private function recalculate( $math, $main_value, $sub_value ) {
|
215 |
+
$result = 0;
|
216 |
+
|
217 |
+
if ( is_numeric( $main_value ) && is_numeric( $sub_value ) ) {
|
218 |
+
switch ( $math ) {
|
219 |
+
case 'add':
|
220 |
+
$result = $main_value + $sub_value;
|
221 |
+
break;
|
222 |
+
|
223 |
+
case 'subtract':
|
224 |
+
$result = $main_value - $sub_value;
|
225 |
+
break;
|
226 |
+
|
227 |
+
case 'multiply':
|
228 |
+
$result = $main_value * $sub_value;
|
229 |
+
break;
|
230 |
+
|
231 |
+
case 'divide':
|
232 |
+
$result = 0 !== $sub_value ? $main_value / $sub_value : 0;
|
233 |
+
break;
|
234 |
+
}
|
235 |
+
}
|
236 |
+
return $result;
|
237 |
+
}
|
238 |
+
}
|
239 |
+
// End of TVC_Feed_Value_Editors class
|
240 |
+
endif;
|
includes/application/class-tvc-schedules.php
ADDED
@@ -0,0 +1,147 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Product Schedules Class.
|
5 |
+
*
|
6 |
+
* @package TVC Product Feed Manager/Application/Classes
|
7 |
+
* @version 1.1.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
|
15 |
+
if ( ! class_exists( 'TVC_Schedules' ) ) :
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Feed Schedules Class
|
19 |
+
*/
|
20 |
+
class TVC_Schedules {
|
21 |
+
|
22 |
+
/* --------------------------------------------------------------------------------------------------*
|
23 |
+
* Public functions
|
24 |
+
* -------------------------------------------------------------------------------------------------- */
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Initiates the automatic feed updates
|
28 |
+
*/
|
29 |
+
public function update_active_feeds() {
|
30 |
+
$data_class = new TVC_Data();
|
31 |
+
|
32 |
+
$current_timestamp = date( 'Y-m-d H:i:s', current_time( 'timestamp' ) );
|
33 |
+
$active_feeds_schedules = $data_class->get_schedule_data();
|
34 |
+
$failed_feeds = $data_class->get_failed_feeds();
|
35 |
+
$active_feed_id = null;
|
36 |
+
|
37 |
+
// update scheduled feeds
|
38 |
+
foreach ( $active_feeds_schedules as $schedule ) {
|
39 |
+
$active_feed_id = $schedule['product_feed_id'];
|
40 |
+
$update_time = $this->new_activation_time( $schedule['updated'], $schedule['schedule'] );
|
41 |
+
|
42 |
+
// activate the feed update when the update time is reached
|
43 |
+
if ( $update_time < $current_timestamp ) {
|
44 |
+
TVC_Feed_Controller::add_id_to_feed_queue( $schedule['product_feed_id'] );
|
45 |
+
|
46 |
+
$data_class->update_feed_status( $schedule['product_feed_id'], 4 ); // feed status to waiting in queue
|
47 |
+
}
|
48 |
+
}
|
49 |
+
|
50 |
+
// if there is no feed processing in progress and the feed queue is not empty, start updating the current feed
|
51 |
+
if ( ! TVC_Feed_Controller::feed_queue_is_empty() && ! TVC_Feed_Controller::feed_is_processing() ) {
|
52 |
+
do_action( 'tvc_automatic_feed_update_triggered', $active_feed_id );
|
53 |
+
$feed_master_class = new TVC_Feed_Master_Class( $active_feed_id );
|
54 |
+
$feed_master_class->update_feed_file( true );
|
55 |
+
}
|
56 |
+
|
57 |
+
// update previously failed feeds
|
58 |
+
if ( 'true' === get_option( 'tvc_auto_feed_fix' ) ) {
|
59 |
+
foreach ( $failed_feeds as $failed_feed ) {
|
60 |
+
TVC_Feed_Controller::add_id_to_feed_queue( $failed_feed['product_feed_id'] );
|
61 |
+
|
62 |
+
// if there is no feed processing in progress, start updating the current feed
|
63 |
+
if ( ! TVC_Feed_Controller::feed_is_processing() ) {
|
64 |
+
do_action( 'tvc_automatic_feed_prepare_update_triggered', $active_feed_id );
|
65 |
+
|
66 |
+
$feed_master_class = new TVC_Feed_Master_Class( $active_feed_id );
|
67 |
+
$feed_master_class->update_feed_file( true );
|
68 |
+
} else {
|
69 |
+
$data_class->update_feed_status( $failed_feed['product_feed_id'], 4 ); // feed status to waiting in queue
|
70 |
+
}
|
71 |
+
}
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
/* --------------------------------------------------------------------------------------------------*
|
76 |
+
* Private functions
|
77 |
+
* -------------------------------------------------------------------------------------------------- */
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Returns the time at which the feed should be updated
|
81 |
+
*
|
82 |
+
* @param string $last_update time string with the data and time the feed has been update last
|
83 |
+
* @param string $update_frequency registered update frequency
|
84 |
+
*
|
85 |
+
* @return string Containing the time in Y-m-d H:i:s format
|
86 |
+
*/
|
87 |
+
private function new_activation_time( $last_update, $update_frequency ) {
|
88 |
+
$update_split = explode( ':', $update_frequency );
|
89 |
+
|
90 |
+
$hrs = isset( $update_split[1] ) ? $update_split[1] : '00';
|
91 |
+
$min = isset( $update_split[2] ) ? $update_split[2] : '00';
|
92 |
+
$freq = isset( $update_split[3] ) ? $update_split[3] : 1;
|
93 |
+
|
94 |
+
$planned_update_time = $hrs . ':' . $min . ':00';
|
95 |
+
$planned_update_time = '00:00:00' !== $planned_update_time ? $planned_update_time : '23:59:00';
|
96 |
+
$last_update_time = date( 'H:i:s', strtotime( $last_update ) );
|
97 |
+
$days = $update_split[0] <= 1
|
98 |
+
&& ( ( strtotime( $last_update_time ) <= strtotime( $planned_update_time ) )
|
99 |
+
|| ( '00' === $hrs && '00' === $min ) )
|
100 |
+
? 0 : $update_split[0];
|
101 |
+
|
102 |
+
if ( $freq < 2 ) { // update only once a day, every $update_split[0] days
|
103 |
+
$update_date = date_add( date_create( date( 'Y-m-d', strtotime( $last_update ) ) ), date_interval_create_from_date_string( $days . ' days' ) );
|
104 |
+
|
105 |
+
return date_format( $update_date, 'Y-m-d' ) . ' ' . $planned_update_time;
|
106 |
+
} else { // update more than once a day
|
107 |
+
$update_hrs = $this->get_update_hours( $freq );
|
108 |
+
$update_date = date_add( date_create( $last_update ), date_interval_create_from_date_string( $update_hrs . ' hours' ) );
|
109 |
+
|
110 |
+
return date_format( $update_date, 'Y-m-d H:i' ) . ':00';
|
111 |
+
}
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Returns the daily update options
|
116 |
+
*
|
117 |
+
* @param string $selection selected number of hours
|
118 |
+
*
|
119 |
+
* @return int Hours difference between updates
|
120 |
+
*/
|
121 |
+
private function get_update_hours( $selection ) {
|
122 |
+
switch ( $selection ) {
|
123 |
+
case '2':
|
124 |
+
return 12;
|
125 |
+
|
126 |
+
case '4':
|
127 |
+
return 6;
|
128 |
+
|
129 |
+
case '6':
|
130 |
+
return 4;
|
131 |
+
|
132 |
+
case '8':
|
133 |
+
return 3;
|
134 |
+
|
135 |
+
case '12':
|
136 |
+
return 2;
|
137 |
+
|
138 |
+
case '24':
|
139 |
+
return 1;
|
140 |
+
|
141 |
+
default:
|
142 |
+
return 24;
|
143 |
+
}
|
144 |
+
}
|
145 |
+
}
|
146 |
+
// end of TVC_Schedules class
|
147 |
+
endif;
|
includes/application/google/class-feed.php
ADDED
@@ -0,0 +1,213 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Google Product Feed Manager Google Feed Class.
|
4 |
+
*
|
5 |
+
* @package Google Product Feed Manager/Channels
|
6 |
+
* @version 11.0
|
7 |
+
*/
|
8 |
+
|
9 |
+
// Prevent direct access
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Google_Feed_Class' ) ) :
|
15 |
+
|
16 |
+
/**
|
17 |
+
* TVC_Google_Feed_Class class
|
18 |
+
*/
|
19 |
+
class TVC_Google_Feed_Class extends TVC_Feed_Master_Class {
|
20 |
+
|
21 |
+
private $_version = '11.0';
|
22 |
+
|
23 |
+
public function __construct() {
|
24 |
+
parent::__construct();
|
25 |
+
}
|
26 |
+
|
27 |
+
public function get_version() {
|
28 |
+
return $this->_version;
|
29 |
+
}
|
30 |
+
|
31 |
+
public function get_file_text() {
|
32 |
+
return $this->generate_file_text( '1', 'google_product_category', 'description', 'xml' );
|
33 |
+
}
|
34 |
+
|
35 |
+
public function woocommerce_to_feed_fields() {
|
36 |
+
$fields = new stdClass();
|
37 |
+
|
38 |
+
// ALERT! Any changes made to this object also need to be done to the woocommerceToGoogleFields() function in the google-source.js file
|
39 |
+
$fields->id = 'ID';
|
40 |
+
$fields->title = 'post_title';
|
41 |
+
$fields->google_product_category = 'category';
|
42 |
+
$fields->description = 'post_content';
|
43 |
+
$fields->link = 'permalink';
|
44 |
+
$fields->image_link = 'attachment_url';
|
45 |
+
$fields->additional_image_link = '_wp_attachement_metadata';
|
46 |
+
$fields->price = '_regular_price';
|
47 |
+
$fields->identifier_exists = 'Fill with a static value';
|
48 |
+
$fields->sale_price = '_sale_price';
|
49 |
+
$fields->sale_price_effective_date = '_sale_price_dates_from';
|
50 |
+
$fields->item_group_id = 'item_group_id';
|
51 |
+
$fields->mpn = 'ID';
|
52 |
+
$fields->tax = 'Use the settings in the Merchant Center';
|
53 |
+
$fields->shipping = 'Use the settings in the Merchant Center';
|
54 |
+
|
55 |
+
return $fields;
|
56 |
+
}
|
57 |
+
|
58 |
+
// overrides the set_feed_output_attribute_levels function in TVC_Feed_Master_Class
|
59 |
+
// ALERT! This function is equivalent for the setGoogleOutputAttributeLevels() function in google-source.js
|
60 |
+
public function set_feed_output_attribute_levels( &$main_data ) {
|
61 |
+
$country = $main_data->country;
|
62 |
+
|
63 |
+
for ( $i = 0; $i < count( $main_data->attributes ); $i ++ ) {
|
64 |
+
if ( '0' === $main_data->attributes[ $i ]->fieldLevel ) {
|
65 |
+
switch ( $main_data->attributes[ $i ]->fieldName ) {
|
66 |
+
case 'google_product_category':
|
67 |
+
$main_data->attributes[ $i ]->fieldLevel = $this->google_needs_product_cat( $main_data->mainCategory ) === true ? 1 : 4;
|
68 |
+
break;
|
69 |
+
|
70 |
+
case 'is_bundle':
|
71 |
+
case 'multipack':
|
72 |
+
$main_data->attributes[ $i ]->fieldLevel = in_array( $country, $this->special_product_countries() ) ? 1 : 4;
|
73 |
+
break;
|
74 |
+
|
75 |
+
case 'brand':
|
76 |
+
$main_data->attributes[ $i ]->fieldLevel = $this->google_requires_brand( $main_data->mainCategory ) === true ? 1 : 4;
|
77 |
+
break;
|
78 |
+
|
79 |
+
case 'item_group_id':
|
80 |
+
$main_data->attributes[ $i ]->fieldLevel = in_array( $country, $this->special_clothing_group_countries() ) ? 1 : 4;
|
81 |
+
break;
|
82 |
+
|
83 |
+
case 'gender':
|
84 |
+
case 'age_group':
|
85 |
+
case 'color':
|
86 |
+
case 'size':
|
87 |
+
if ( in_array( $country, $this->special_clothing_group_countries() )
|
88 |
+
&& $this->google_clothing_and_accessories( $main_data->mainCategory ) === true ) {
|
89 |
+
$main_data->attributes[ $i ]->fieldLevel = 1;
|
90 |
+
} else {
|
91 |
+
$main_data->attributes[ $i ]->fieldLevel = 4;
|
92 |
+
}
|
93 |
+
|
94 |
+
break;
|
95 |
+
|
96 |
+
case 'tax':
|
97 |
+
// In accordance with the Google Feed Specifications update of september 2015
|
98 |
+
$main_data->attributes[ $i ]->fieldLevel = 'US' === $country ? 1 : 4;
|
99 |
+
break;
|
100 |
+
|
101 |
+
case 'shipping':
|
102 |
+
// In accordance with the Google Feed Specifications update of september 2015
|
103 |
+
$main_data->attributes[ $i ]->fieldLevel = in_array( $country, $this->special_shipping_countries() ) ? 1 : 4;
|
104 |
+
break;
|
105 |
+
|
106 |
+
case 'subscription_cost':
|
107 |
+
case 'subscription_cost-period':
|
108 |
+
case 'subscription_cost-period_length':
|
109 |
+
case 'subscription_cost-amount':
|
110 |
+
$main_data->attributes[ $i ]->fieldLevel = in_array( $country, $this->special_subscription_countries() ) ? 4 : 0;
|
111 |
+
break;
|
112 |
+
|
113 |
+
default:
|
114 |
+
break;
|
115 |
+
}
|
116 |
+
|
117 |
+
$main_data->attributes[ $i ]->isActive =
|
118 |
+
$this->set_attribute_status( (int) $main_data->attributes[ $i ]->fieldLevel, $main_data->attributes[ $i ]->value );
|
119 |
+
}
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
public function keys_that_have_sub_tags() {
|
124 |
+
return array( 'installment', 'loyalty_points', 'shipping', 'tax', 'subscription_cost' );
|
125 |
+
}
|
126 |
+
|
127 |
+
// ALERT! This function is equivalent to the tvc_doublesFieldsAllowed() function in the tvc_google-source.js file
|
128 |
+
public function keys_that_can_be_used_more_than_once() {
|
129 |
+
return array( 'display_ads_similar_id', 'excluded_destination', 'adwords_labels', 'shipping' );
|
130 |
+
}
|
131 |
+
|
132 |
+
public function sub_keys_for_sub_tags() {
|
133 |
+
return array(
|
134 |
+
'installment-months',
|
135 |
+
'installment-amount',
|
136 |
+
'loyalty_points-name',
|
137 |
+
'loyalty_points-pointsValue',
|
138 |
+
'loyalty_points-ratio',
|
139 |
+
'shipping-country',
|
140 |
+
'shipping-region',
|
141 |
+
'shipping-service',
|
142 |
+
'shipping-price',
|
143 |
+
'tax-country',
|
144 |
+
'tax-region',
|
145 |
+
'tax-rate',
|
146 |
+
'tax-tax_ship',
|
147 |
+
'subscription_cost-period',
|
148 |
+
'subscription_cost-period_length',
|
149 |
+
'subscription_cost-amount',
|
150 |
+
);
|
151 |
+
}
|
152 |
+
|
153 |
+
// ALERT! This function is equivalent to the googleSpecialClothingGroupCountries() function in google-source.js
|
154 |
+
private function special_clothing_group_countries() {
|
155 |
+
return array( 'US', 'GB', 'DE', 'FR', 'JP', 'BR' ); // Brazil added based on the new Feed Specifications from september 2015
|
156 |
+
}
|
157 |
+
|
158 |
+
// ALERT! This function is equivalent to the googleSpecialShippingCountries() function in google-source.js
|
159 |
+
private function special_shipping_countries() {
|
160 |
+
return array( 'US', 'GB', 'DE', 'AU', 'FR', 'CH', 'CZ', 'NL', 'IT', 'ES', 'JP' );
|
161 |
+
}
|
162 |
+
|
163 |
+
// ALERT! This function is equivalent to the googleSpecialProductCountries() function in google-source.js
|
164 |
+
private function special_product_countries() {
|
165 |
+
return array( 'US', 'GB', 'DE', 'AU', 'FR', 'CH', 'CZ', 'NL', 'IT', 'ES', 'JP', 'BR' );
|
166 |
+
}
|
167 |
+
|
168 |
+
// ALERT! This function is equivalent to the googleSpecialSubscriptionCountries() function in google-source.js
|
169 |
+
private function special_subscription_countries() {
|
170 |
+
return array( 'DE', 'FR', 'GB' );
|
171 |
+
}
|
172 |
+
|
173 |
+
private function google_clothing_and_accessories( $category ) {
|
174 |
+
return stristr( $category, 'Apparel & Accessories' ) !== false ? true : false;
|
175 |
+
}
|
176 |
+
|
177 |
+
private function google_needs_product_cat( $category ) {
|
178 |
+
return stristr( $category, 'Apparel & Accessories' ) !== false
|
179 |
+
|| stristr( $category, 'Media' ) !== false
|
180 |
+
|| stristr( $category, 'Software' ) !== false ? true : false;
|
181 |
+
}
|
182 |
+
|
183 |
+
private function google_requires_brand( $category ) {
|
184 |
+
return false === stristr( $category, 'Media' ) ? true : false;
|
185 |
+
}
|
186 |
+
|
187 |
+
protected function header( $title, $description = '' ) {
|
188 |
+
// the check for convert_to_data_string function can be remove when all users have switched to plugin version 1.6 or higher
|
189 |
+
$title_string = method_exists( $this, 'data_string' ) ? $this->data_string( $title )
|
190 |
+
: $this->convert_to_character_data_string( $title );
|
191 |
+
$home_link = method_exists( $this, 'data_string' ) ? $this->data_string( get_option( 'home' ) )
|
192 |
+
: $this->convert_to_character_data_string( get_option( 'home' ) );
|
193 |
+
$descr = '' !== $description ? $description : $title;
|
194 |
+
$description_string = method_exists( $this, 'data_string' ) ? $this->data_string( $descr )
|
195 |
+
: $this->convert_to_character_data_string( $descr );
|
196 |
+
$title_tag = '<wf-connection-string>';
|
197 |
+
|
198 |
+
return '<?xml version="1.0"?>
|
199 |
+
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
|
200 |
+
<channel>
|
201 |
+
<title>' . $title_string . '</title>'
|
202 |
+
. $title_tag . $home_link . '</link>
|
203 |
+
<description>' . $description_string . '</description>';
|
204 |
+
}
|
205 |
+
|
206 |
+
protected function footer() {
|
207 |
+
return '</channel></rss>';
|
208 |
+
}
|
209 |
+
}
|
210 |
+
|
211 |
+
// end of TVC_Google_Feed_Class
|
212 |
+
|
213 |
+
endif;
|
includes/application/google/gmc.txt
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
id
|
2 |
+
offerId
|
3 |
+
title
|
4 |
+
description
|
5 |
+
item_group_id
|
6 |
+
link
|
7 |
+
image_link
|
8 |
+
content_language
|
9 |
+
target_country
|
10 |
+
channel
|
11 |
+
age_group
|
12 |
+
availability
|
13 |
+
availability_date
|
14 |
+
brand
|
15 |
+
color
|
16 |
+
condition
|
17 |
+
gender
|
18 |
+
google_product_category
|
19 |
+
gtin
|
20 |
+
item_group_id
|
21 |
+
mpn
|
22 |
+
price
|
23 |
+
sizes
|
includes/application/google/gmc_attrbutes.json
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[
|
2 |
+
{
|
3 |
+
"field": "id",
|
4 |
+
"required": 1,
|
5 |
+
"desc": "Your product’s unique identifier",
|
6 |
+
"wAttribute": "ID"
|
7 |
+
},
|
8 |
+
{
|
9 |
+
"field": "title",
|
10 |
+
"required": 1,
|
11 |
+
"desc": "Your product’s name",
|
12 |
+
"wAttribute": "post_title"
|
13 |
+
},
|
14 |
+
{
|
15 |
+
"field": "description",
|
16 |
+
"required": 1,
|
17 |
+
"desc": "Your product’s description",
|
18 |
+
"wAttribute": "post_excerpt"
|
19 |
+
},
|
20 |
+
{
|
21 |
+
"field": "link",
|
22 |
+
"desc": "Your product’s landing page",
|
23 |
+
"required": 1
|
24 |
+
},
|
25 |
+
{
|
26 |
+
"field": "image_link",
|
27 |
+
"required": 1,
|
28 |
+
"desc": "The URL of your product’s main image",
|
29 |
+
"wAttribute": "_wp_attached_file"
|
30 |
+
},
|
31 |
+
{
|
32 |
+
"field": "price",
|
33 |
+
"required": 1,
|
34 |
+
"desc": "Your product’s price",
|
35 |
+
"wAttribute": "_sale_price"
|
36 |
+
|
37 |
+
},
|
38 |
+
{
|
39 |
+
"field": "gtin",
|
40 |
+
"desc": "Your product’s Global Trade Item Number (GTIN). Required for all new products with an assigned GTIN.",
|
41 |
+
"wAttribute": "tvc_product_gtin"
|
42 |
+
},
|
43 |
+
{
|
44 |
+
"field": "mpn",
|
45 |
+
"desc": "Your product’s Global Trade Item Number (GTIN). Required for all new products with an assigned GTIN.",
|
46 |
+
"wAttribute": "tvc_product_mpn"
|
47 |
+
},
|
48 |
+
{
|
49 |
+
"field": "offer_id",
|
50 |
+
"required": 1,
|
51 |
+
"desc": "offer id",
|
52 |
+
"wAttribute": "ID"
|
53 |
+
},
|
54 |
+
{
|
55 |
+
"field": "brand",
|
56 |
+
"desc": "Your product’s brand name",
|
57 |
+
"wAttribute": "tvc_product_brand"
|
58 |
+
},
|
59 |
+
{
|
60 |
+
"field": "availability",
|
61 |
+
"desc": "Your product's availability",
|
62 |
+
"wAttribute": "_stock_status"
|
63 |
+
},
|
64 |
+
{
|
65 |
+
"field": "item_group_id",
|
66 |
+
"desc": "ID for a group of products that come in different versions (variants)"
|
67 |
+
},
|
68 |
+
{
|
69 |
+
"field": "sizes",
|
70 |
+
"desc": "Your product’s size"
|
71 |
+
},
|
72 |
+
{
|
73 |
+
"field": "color",
|
74 |
+
"desc": "Your product’s color(s)"
|
75 |
+
},
|
76 |
+
{
|
77 |
+
"field": "age_group",
|
78 |
+
"desc": "The demographic for which your product is intended"
|
79 |
+
},
|
80 |
+
{
|
81 |
+
"field": "gender",
|
82 |
+
"desc": "The gender for which your product is intended"
|
83 |
+
},
|
84 |
+
{
|
85 |
+
"field": "condition",
|
86 |
+
"desc": "The condition of your product at time of sale"
|
87 |
+
},
|
88 |
+
{
|
89 |
+
|
90 |
+
"field": "shipping",
|
91 |
+
"desc": "Your product's shipping cost and the locations your product ships to"
|
92 |
+
},
|
93 |
+
{
|
94 |
+
|
95 |
+
"field": "tax",
|
96 |
+
"desc": "Your product’s sales tax rate in percent"
|
97 |
+
},
|
98 |
+
{
|
99 |
+
"field": "product_type",
|
100 |
+
"desc": "Product category that you define for your product"
|
101 |
+
},
|
102 |
+
{
|
103 |
+
"field": "google_product_category",
|
104 |
+
"desc": "product category"
|
105 |
+
},
|
106 |
+
{
|
107 |
+
"field": "content_language",
|
108 |
+
"desc": "content language"
|
109 |
+
},
|
110 |
+
{
|
111 |
+
"field": "target_country",
|
112 |
+
"desc": "Country for Google Shopping Listing"
|
113 |
+
},
|
114 |
+
{
|
115 |
+
"field": "channel",
|
116 |
+
"desc": "channel"
|
117 |
+
}
|
118 |
+
]
|
includes/application/google/google.txt
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
1 1 id
|
2 |
+
2 1 title
|
3 |
+
3 1 description
|
4 |
+
4 0 google_product_category
|
5 |
+
5 4 product_type
|
6 |
+
6 1 link
|
7 |
+
7 4 mobile_link
|
8 |
+
8 1 image_link
|
9 |
+
9 1 price
|
10 |
+
10 1 condition
|
11 |
+
11 1 availability
|
12 |
+
12 4 availability_date
|
13 |
+
13 0 brand
|
14 |
+
14 1 gtin
|
15 |
+
15 4 mpn
|
16 |
+
16 0 item_group_id
|
17 |
+
17 4 additional_image_link
|
18 |
+
18 4 sale_price
|
19 |
+
19 4 sale_price_effective_date
|
20 |
+
20 0 gender
|
21 |
+
21 0 age_group
|
22 |
+
22 0 color
|
23 |
+
23 0 size
|
24 |
+
24 4 material
|
25 |
+
25 4 pattern
|
26 |
+
26 4 shipping_weight
|
27 |
+
27 4 expiration_date
|
28 |
+
28 4 adwords_redirect
|
29 |
+
29 1 adult
|
30 |
+
30 0 multipack
|
31 |
+
31 1 identifier_exists
|
32 |
+
32 4 size_type
|
33 |
+
33 4 size_system
|
34 |
+
34 0 shipping
|
35 |
+
35 4 shipping_label
|
36 |
+
36 0 is_bundle
|
37 |
+
37 4 custom_label_0
|
38 |
+
38 4 custom_label_1
|
39 |
+
39 4 custom_label_2
|
40 |
+
40 4 custom_label_3
|
41 |
+
41 4 custom_label_4
|
42 |
+
42 4 unit_pricing_measure
|
43 |
+
43 4 unit_pricing_base_measure
|
44 |
+
44 4 energy_efficiency_class
|
45 |
+
45 4 min_energy_efficiency_class
|
46 |
+
46 4 max_energy_efficiency_class
|
47 |
+
47 0 tax
|
48 |
+
48 4 installment
|
49 |
+
49 4 loyalty_points
|
50 |
+
50 4 promotion_id
|
51 |
+
51 4 shipping_length
|
52 |
+
52 4 shipping_width
|
53 |
+
53 4 shipping_height
|
54 |
+
54 4 installment-months
|
55 |
+
55 4 installment-amount
|
56 |
+
56 4 loyalty_points-name
|
57 |
+
57 4 loyalty_points-pointsValue
|
58 |
+
58 4 loyalty_points-ratio
|
59 |
+
59 4 shipping-country
|
60 |
+
60 4 shipping-region
|
61 |
+
61 4 shipping-service
|
62 |
+
62 4 shipping-price
|
63 |
+
63 4 transit_time_label
|
64 |
+
64 4 tax-country
|
65 |
+
65 4 tax-region
|
66 |
+
66 4 tax-rate
|
67 |
+
67 4 tax-tax_ship
|
68 |
+
68 4 tax_category
|
69 |
+
69 4 display_ads_id
|
70 |
+
70 4 display_ads_similar_id
|
71 |
+
71 4 display_ads_title
|
72 |
+
72 4 display_ads_link
|
73 |
+
73 4 display_ads_value
|
74 |
+
74 4 excluded_destination
|
75 |
+
75 4 included_destination
|
76 |
+
76 4 adwords_grouping
|
77 |
+
77 4 adwords_labels
|
78 |
+
78 4 min_handling_time
|
79 |
+
79 4 max_handling_time
|
80 |
+
80 4 cost_of_goods_sold
|
81 |
+
81 0 subscription_cost
|
82 |
+
82 0 subscription_cost-period
|
83 |
+
83 0 subscription_cost-period_length
|
84 |
+
84 0 subscription_cost-amount
|
includes/application/google/taxonomy.en-US.txt
ADDED
@@ -0,0 +1,5583 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Google_Product_Taxonomy_Version: 2019-07-10
|
2 |
+
Animals & Pet Supplies
|
3 |
+
Animals & Pet Supplies > Live Animals
|
4 |
+
Animals & Pet Supplies > Pet Supplies
|
5 |
+
Animals & Pet Supplies > Pet Supplies > Bird Supplies
|
6 |
+
Animals & Pet Supplies > Pet Supplies > Bird Supplies > Bird Cage Accessories
|
7 |
+
Animals & Pet Supplies > Pet Supplies > Bird Supplies > Bird Cage Accessories > Bird Cage Bird Baths
|
8 |
+
Animals & Pet Supplies > Pet Supplies > Bird Supplies > Bird Cage Accessories > Bird Cage Food & Water Dishes
|
9 |
+
Animals & Pet Supplies > Pet Supplies > Bird Supplies > Bird Cages & Stands
|
10 |
+
Animals & Pet Supplies > Pet Supplies > Bird Supplies > Bird Food
|
11 |
+
Animals & Pet Supplies > Pet Supplies > Bird Supplies > Bird Gyms & Playstands
|
12 |
+
Animals & Pet Supplies > Pet Supplies > Bird Supplies > Bird Ladders & Perches
|
13 |
+
Animals & Pet Supplies > Pet Supplies > Bird Supplies > Bird Toys
|
14 |
+
Animals & Pet Supplies > Pet Supplies > Bird Supplies > Bird Treats
|
15 |
+
Animals & Pet Supplies > Pet Supplies > Cat Supplies
|
16 |
+
Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Apparel
|
17 |
+
Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Beds
|
18 |
+
Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Food
|
19 |
+
Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Food > Non-prescription Cat Food
|
20 |
+
Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Food > Prescription Cat Food
|
21 |
+
Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Furniture
|
22 |
+
Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Furniture Accessories
|
23 |
+
Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Litter
|
24 |
+
Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Litter Box Liners
|
25 |
+
Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Litter Box Mats
|
26 |
+
Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Litter Boxes
|
27 |
+
Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Toys
|
28 |
+
Animals & Pet Supplies > Pet Supplies > Cat Supplies > Cat Treats
|
29 |
+
Animals & Pet Supplies > Pet Supplies > Dog Supplies
|
30 |
+
Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Apparel
|
31 |
+
Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Beds
|
32 |
+
Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Diaper Pads & Liners
|
33 |
+
Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Diapers
|
34 |
+
Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Food
|
35 |
+
Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Food > Non-prescription Dog Food
|
36 |
+
Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Food > Prescription Dog Food
|
37 |
+
Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Houses
|
38 |
+
Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Kennel & Run Accessories
|
39 |
+
Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Kennels & Runs
|
40 |
+
Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Toys
|
41 |
+
Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Treadmills
|
42 |
+
Animals & Pet Supplies > Pet Supplies > Dog Supplies > Dog Treats
|
43 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies
|
44 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium & Pond Tubing
|
45 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Air Stones & Diffusers
|
46 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Cleaning Supplies
|
47 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Decor
|
48 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Filters
|
49 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Fish Nets
|
50 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Gravel & Substrates
|
51 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Lighting
|
52 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Overflow Boxes
|
53 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Stands
|
54 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Temperature Controllers
|
55 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquarium Water Treatments
|
56 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquariums
|
57 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Aquatic Plant Fertilizers
|
58 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Fish Feeders
|
59 |
+
Animals & Pet Supplies > Pet Supplies > Fish Supplies > Fish Food
|
60 |
+
Animals & Pet Supplies > Pet Supplies > Pet Agility Equipment
|
61 |
+
Animals & Pet Supplies > Pet Supplies > Pet Apparel Hangers
|
62 |
+
Animals & Pet Supplies > Pet Supplies > Pet Bed Accessories
|
63 |
+
Animals & Pet Supplies > Pet Supplies > Pet Bells & Charms
|
64 |
+
Animals & Pet Supplies > Pet Supplies > Pet Biometric Monitors
|
65 |
+
Animals & Pet Supplies > Pet Supplies > Pet Biometric Monitors > Pet Glucose Meters
|
66 |
+
Animals & Pet Supplies > Pet Supplies > Pet Biometric Monitors > Pet Pedometers
|
67 |
+
Animals & Pet Supplies > Pet Supplies > Pet Biometric Monitors > Pet Thermometers
|
68 |
+
Animals & Pet Supplies > Pet Supplies > Pet Bowl Mats
|
69 |
+
Animals & Pet Supplies > Pet Supplies > Pet Bowl Stands
|
70 |
+
Animals & Pet Supplies > Pet Supplies > Pet Bowls, Feeders & Waterers
|
71 |
+
Animals & Pet Supplies > Pet Supplies > Pet Carrier & Crate Accessories
|
72 |
+
Animals & Pet Supplies > Pet Supplies > Pet Carriers & Crates
|
73 |
+
Animals & Pet Supplies > Pet Supplies > Pet Collars & Harnesses
|
74 |
+
Animals & Pet Supplies > Pet Supplies > Pet Containment Systems
|
75 |
+
Animals & Pet Supplies > Pet Supplies > Pet Door Accessories
|
76 |
+
Animals & Pet Supplies > Pet Supplies > Pet Doors
|
77 |
+
Animals & Pet Supplies > Pet Supplies > Pet Eye Drops & Lubricants
|
78 |
+
Animals & Pet Supplies > Pet Supplies > Pet First Aid & Emergency Kits
|
79 |
+
Animals & Pet Supplies > Pet Supplies > Pet Flea & Tick Control
|
80 |
+
Animals & Pet Supplies > Pet Supplies > Pet Food Containers
|
81 |
+
Animals & Pet Supplies > Pet Supplies > Pet Food Scoops
|
82 |
+
Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies
|
83 |
+
Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Combs & Brushes
|
84 |
+
Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Fragrances & Deodorizing Sprays
|
85 |
+
Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Hair Clippers & Trimmers
|
86 |
+
Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Hair Dryers
|
87 |
+
Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Nail Polish
|
88 |
+
Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Nail Tools
|
89 |
+
Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Shampoo & Conditioner
|
90 |
+
Animals & Pet Supplies > Pet Supplies > Pet Grooming Supplies > Pet Wipes
|
91 |
+
Animals & Pet Supplies > Pet Supplies > Pet Heating Pad Accessories
|
92 |
+
Animals & Pet Supplies > Pet Supplies > Pet Heating Pads
|
93 |
+
Animals & Pet Supplies > Pet Supplies > Pet ID Tags
|
94 |
+
Animals & Pet Supplies > Pet Supplies > Pet Leash Extensions
|
95 |
+
Animals & Pet Supplies > Pet Supplies > Pet Leashes
|
96 |
+
Animals & Pet Supplies > Pet Supplies > Pet Medical Collars
|
97 |
+
Animals & Pet Supplies > Pet Supplies > Pet Medical Tape & Bandages
|
98 |
+
Animals & Pet Supplies > Pet Supplies > Pet Medicine
|
99 |
+
Animals & Pet Supplies > Pet Supplies > Pet Muzzles
|
100 |
+
Animals & Pet Supplies > Pet Supplies > Pet Oral Care Supplies
|
101 |
+
Animals & Pet Supplies > Pet Supplies > Pet Playpens
|
102 |
+
Animals & Pet Supplies > Pet Supplies > Pet Steps & Ramps
|
103 |
+
Animals & Pet Supplies > Pet Supplies > Pet Strollers
|
104 |
+
Animals & Pet Supplies > Pet Supplies > Pet Sunscreen
|
105 |
+
Animals & Pet Supplies > Pet Supplies > Pet Training Aids
|
106 |
+
Animals & Pet Supplies > Pet Supplies > Pet Training Aids > Pet Training Clickers & Treat Dispensers
|
107 |
+
Animals & Pet Supplies > Pet Supplies > Pet Training Aids > Pet Training Pad Holders
|
108 |
+
Animals & Pet Supplies > Pet Supplies > Pet Training Aids > Pet Training Pads
|
109 |
+
Animals & Pet Supplies > Pet Supplies > Pet Training Aids > Pet Training Sprays & Solutions
|
110 |
+
Animals & Pet Supplies > Pet Supplies > Pet Vitamins & Supplements
|
111 |
+
Animals & Pet Supplies > Pet Supplies > Pet Waste Bag Dispensers & Holders
|
112 |
+
Animals & Pet Supplies > Pet Supplies > Pet Waste Bags
|
113 |
+
Animals & Pet Supplies > Pet Supplies > Pet Waste Disposal Systems & Tools
|
114 |
+
Animals & Pet Supplies > Pet Supplies > Reptile & Amphibian Supplies
|
115 |
+
Animals & Pet Supplies > Pet Supplies > Reptile & Amphibian Supplies > Reptile & Amphibian Food
|
116 |
+
Animals & Pet Supplies > Pet Supplies > Reptile & Amphibian Supplies > Reptile & Amphibian Habitat Accessories
|
117 |
+
Animals & Pet Supplies > Pet Supplies > Reptile & Amphibian Supplies > Reptile & Amphibian Habitat Heating & Lighting
|
118 |
+
Animals & Pet Supplies > Pet Supplies > Reptile & Amphibian Supplies > Reptile & Amphibian Habitats
|
119 |
+
Animals & Pet Supplies > Pet Supplies > Reptile & Amphibian Supplies > Reptile & Amphibian Substrates
|
120 |
+
Animals & Pet Supplies > Pet Supplies > Small Animal Supplies
|
121 |
+
Animals & Pet Supplies > Pet Supplies > Small Animal Supplies > Small Animal Bedding
|
122 |
+
Animals & Pet Supplies > Pet Supplies > Small Animal Supplies > Small Animal Food
|
123 |
+
Animals & Pet Supplies > Pet Supplies > Small Animal Supplies > Small Animal Habitat Accessories
|
124 |
+
Animals & Pet Supplies > Pet Supplies > Small Animal Supplies > Small Animal Habitats & Cages
|
125 |
+
Animals & Pet Supplies > Pet Supplies > Small Animal Supplies > Small Animal Treats
|
126 |
+
Animals & Pet Supplies > Pet Supplies > Vehicle Pet Barriers
|
127 |
+
Apparel & Accessories
|
128 |
+
Apparel & Accessories > Clothing
|
129 |
+
Apparel & Accessories > Clothing > Activewear
|
130 |
+
Apparel & Accessories > Clothing > Activewear > Bicycle Activewear
|
131 |
+
Apparel & Accessories > Clothing > Activewear > Bicycle Activewear > Bicycle Bibs
|
132 |
+
Apparel & Accessories > Clothing > Activewear > Bicycle Activewear > Bicycle Jerseys
|
133 |
+
Apparel & Accessories > Clothing > Activewear > Bicycle Activewear > Bicycle Shorts & Briefs
|
134 |
+
Apparel & Accessories > Clothing > Activewear > Bicycle Activewear > Bicycle Skinsuits
|
135 |
+
Apparel & Accessories > Clothing > Activewear > Bicycle Activewear > Bicycle Tights
|
136 |
+
Apparel & Accessories > Clothing > Activewear > Boxing Shorts
|
137 |
+
Apparel & Accessories > Clothing > Activewear > Dance Dresses, Skirts & Costumes
|
138 |
+
Apparel & Accessories > Clothing > Activewear > Football Pants
|
139 |
+
Apparel & Accessories > Clothing > Activewear > Hunting Clothing
|
140 |
+
Apparel & Accessories > Clothing > Activewear > Hunting Clothing > Ghillie Suits
|
141 |
+
Apparel & Accessories > Clothing > Activewear > Hunting Clothing > Hunting & Fishing Vests
|
142 |
+
Apparel & Accessories > Clothing > Activewear > Hunting Clothing > Hunting & Tactical Pants
|
143 |
+
Apparel & Accessories > Clothing > Activewear > Martial Arts Shorts
|
144 |
+
Apparel & Accessories > Clothing > Activewear > Motorcycle Protective Clothing
|
145 |
+
Apparel & Accessories > Clothing > Activewear > Motorcycle Protective Clothing > Motorcycle Jackets
|
146 |
+
Apparel & Accessories > Clothing > Activewear > Motorcycle Protective Clothing > Motorcycle Pants
|
147 |
+
Apparel & Accessories > Clothing > Activewear > Motorcycle Protective Clothing > Motorcycle Suits
|
148 |
+
Apparel & Accessories > Clothing > Activewear > Paintball Clothing
|
149 |
+
Apparel & Accessories > Clothing > Baby & Toddler Clothing
|
150 |
+
Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Bottoms
|
151 |
+
Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Diaper Covers
|
152 |
+
Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Dresses
|
153 |
+
Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Outerwear
|
154 |
+
Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Outfits
|
155 |
+
Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Sleepwear
|
156 |
+
Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Socks & Tights
|
157 |
+
Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Swimwear
|
158 |
+
Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby & Toddler Tops
|
159 |
+
Apparel & Accessories > Clothing > Baby & Toddler Clothing > Baby One-Pieces
|
160 |
+
Apparel & Accessories > Clothing > Baby & Toddler Clothing > Toddler Underwear
|
161 |
+
Apparel & Accessories > Clothing > Dresses
|
162 |
+
Apparel & Accessories > Clothing > One-Pieces
|
163 |
+
Apparel & Accessories > Clothing > One-Pieces > Jumpsuits & Rompers
|
164 |
+
Apparel & Accessories > Clothing > One-Pieces > Leotards & Unitards
|
165 |
+
Apparel & Accessories > Clothing > One-Pieces > Overalls
|
166 |
+
Apparel & Accessories > Clothing > Outerwear
|
167 |
+
Apparel & Accessories > Clothing > Outerwear > Chaps
|
168 |
+
Apparel & Accessories > Clothing > Outerwear > Coats & Jackets
|
169 |
+
Apparel & Accessories > Clothing > Outerwear > Rain Pants
|
170 |
+
Apparel & Accessories > Clothing > Outerwear > Rain Suits
|
171 |
+
Apparel & Accessories > Clothing > Outerwear > Snow Pants & Suits
|
172 |
+
Apparel & Accessories > Clothing > Outerwear > Vests
|
173 |
+
Apparel & Accessories > Clothing > Outfit Sets
|
174 |
+
Apparel & Accessories > Clothing > Pants
|
175 |
+
Apparel & Accessories > Clothing > Shirts & Tops
|
176 |
+
Apparel & Accessories > Clothing > Shorts
|
177 |
+
Apparel & Accessories > Clothing > Skirts
|
178 |
+
Apparel & Accessories > Clothing > Skorts
|
179 |
+
Apparel & Accessories > Clothing > Sleepwear & Loungewear
|
180 |
+
Apparel & Accessories > Clothing > Sleepwear & Loungewear > Loungewear
|
181 |
+
Apparel & Accessories > Clothing > Sleepwear & Loungewear > Nightgowns
|
182 |
+
Apparel & Accessories > Clothing > Sleepwear & Loungewear > Pajamas
|
183 |
+
Apparel & Accessories > Clothing > Sleepwear & Loungewear > Robes
|
184 |
+
Apparel & Accessories > Clothing > Suits
|
185 |
+
Apparel & Accessories > Clothing > Suits > Pant Suits
|
186 |
+
Apparel & Accessories > Clothing > Suits > Skirt Suits
|
187 |
+
Apparel & Accessories > Clothing > Suits > Tuxedos
|
188 |
+
Apparel & Accessories > Clothing > Swimwear
|
189 |
+
Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing
|
190 |
+
Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Dirndls
|
191 |
+
Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Hakama Trousers
|
192 |
+
Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Japanese Black Formal Wear
|
193 |
+
Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Kimono Outerwear
|
194 |
+
Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Kimonos
|
195 |
+
Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Religious Ceremonial Clothing
|
196 |
+
Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Religious Ceremonial Clothing > Baptism & Communion Dresses
|
197 |
+
Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Saris & Lehengas
|
198 |
+
Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Traditional Leather Pants
|
199 |
+
Apparel & Accessories > Clothing > Traditional & Ceremonial Clothing > Yukata
|
200 |
+
Apparel & Accessories > Clothing > Underwear & Socks
|
201 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Bra Accessories
|
202 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Bra Accessories > Bra Strap Pads
|
203 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Bra Accessories > Bra Straps & Extenders
|
204 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Bra Accessories > Breast Enhancing Inserts
|
205 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Bra Accessories > Breast Petals & Concealers
|
206 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Bras
|
207 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Hosiery
|
208 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Jock Straps
|
209 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Lingerie
|
210 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Lingerie Accessories
|
211 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Lingerie Accessories > Garter Belts
|
212 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Lingerie Accessories > Garters
|
213 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Long Johns
|
214 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Petticoats & Pettipants
|
215 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Shapewear
|
216 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Socks
|
217 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Undershirts
|
218 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Underwear
|
219 |
+
Apparel & Accessories > Clothing > Underwear & Socks > Underwear Slips
|
220 |
+
Apparel & Accessories > Clothing > Uniforms
|
221 |
+
Apparel & Accessories > Clothing > Uniforms > Contractor Pants & Coveralls
|
222 |
+
Apparel & Accessories > Clothing > Uniforms > Flight Suits
|
223 |
+
Apparel & Accessories > Clothing > Uniforms > Food Service Uniforms
|
224 |
+
Apparel & Accessories > Clothing > Uniforms > Food Service Uniforms > Chef's Hats
|
225 |
+
Apparel & Accessories > Clothing > Uniforms > Food Service Uniforms > Chef's Jackets
|
226 |
+
Apparel & Accessories > Clothing > Uniforms > Food Service Uniforms > Chef's Pants
|
227 |
+
Apparel & Accessories > Clothing > Uniforms > Military Uniforms
|
228 |
+
Apparel & Accessories > Clothing > Uniforms > School Uniforms
|
229 |
+
Apparel & Accessories > Clothing > Uniforms > Security Uniforms
|
230 |
+
Apparel & Accessories > Clothing > Uniforms > Sports Uniforms
|
231 |
+
Apparel & Accessories > Clothing > Uniforms > Sports Uniforms > Baseball Uniforms
|
232 |
+
Apparel & Accessories > Clothing > Uniforms > Sports Uniforms > Basketball Uniforms
|
233 |
+
Apparel & Accessories > Clothing > Uniforms > Sports Uniforms > Cheerleading Uniforms
|
234 |
+
Apparel & Accessories > Clothing > Uniforms > Sports Uniforms > Cricket Uniforms
|
235 |
+
Apparel & Accessories > Clothing > Uniforms > Sports Uniforms > Football Uniforms
|
236 |
+
Apparel & Accessories > Clothing > Uniforms > Sports Uniforms > Hockey Uniforms
|
237 |
+
Apparel & Accessories > Clothing > Uniforms > Sports Uniforms > Martial Arts Uniforms
|
238 |
+
Apparel & Accessories > Clothing > Uniforms > Sports Uniforms > Officiating Uniforms
|
239 |
+
Apparel & Accessories > Clothing > Uniforms > Sports Uniforms > Soccer Uniforms
|
240 |
+
Apparel & Accessories > Clothing > Uniforms > Sports Uniforms > Softball Uniforms
|
241 |
+
Apparel & Accessories > Clothing > Uniforms > Sports Uniforms > Wrestling Uniforms
|
242 |
+
Apparel & Accessories > Clothing > Uniforms > White Coats
|
243 |
+
Apparel & Accessories > Clothing > Wedding & Bridal Party Dresses
|
244 |
+
Apparel & Accessories > Clothing > Wedding & Bridal Party Dresses > Bridal Party Dresses
|
245 |
+
Apparel & Accessories > Clothing > Wedding & Bridal Party Dresses > Wedding Dresses
|
246 |
+
Apparel & Accessories > Clothing Accessories
|
247 |
+
Apparel & Accessories > Clothing Accessories > Arm Warmers & Sleeves
|
248 |
+
Apparel & Accessories > Clothing Accessories > Baby & Toddler Clothing Accessories
|
249 |
+
Apparel & Accessories > Clothing Accessories > Baby & Toddler Clothing Accessories > Baby & Toddler Belts
|
250 |
+
Apparel & Accessories > Clothing Accessories > Baby & Toddler Clothing Accessories > Baby & Toddler Gloves & Mittens
|
251 |
+
Apparel & Accessories > Clothing Accessories > Baby & Toddler Clothing Accessories > Baby & Toddler Hats
|
252 |
+
Apparel & Accessories > Clothing Accessories > Baby & Toddler Clothing Accessories > Baby Protective Wear
|
253 |
+
Apparel & Accessories > Clothing Accessories > Balaclavas
|
254 |
+
Apparel & Accessories > Clothing Accessories > Bandanas & Headties
|
255 |
+
Apparel & Accessories > Clothing Accessories > Bandanas & Headties > Bandanas
|
256 |
+
Apparel & Accessories > Clothing Accessories > Bandanas & Headties > Hair Care Wraps
|
257 |
+
Apparel & Accessories > Clothing Accessories > Belt Buckles
|
258 |
+
Apparel & Accessories > Clothing Accessories > Belts
|
259 |
+
Apparel & Accessories > Clothing Accessories > Bridal Accessories
|
260 |
+
Apparel & Accessories > Clothing Accessories > Bridal Accessories > Bridal Veils
|
261 |
+
Apparel & Accessories > Clothing Accessories > Button Studs
|
262 |
+
Apparel & Accessories > Clothing Accessories > Collar Stays
|
263 |
+
Apparel & Accessories > Clothing Accessories > Cufflinks
|
264 |
+
Apparel & Accessories > Clothing Accessories > Decorative Fans
|
265 |
+
Apparel & Accessories > Clothing Accessories > Earmuffs
|
266 |
+
Apparel & Accessories > Clothing Accessories > Gloves & Mittens
|
267 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories
|
268 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Bun & Volume Shapers
|
269 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Combs
|
270 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Extensions
|
271 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Forks & Sticks
|
272 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Nets
|
273 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Pins, Claws & Clips
|
274 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Pins, Claws & Clips > Barrettes
|
275 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Pins, Claws & Clips > Hair Claws & Clips
|
276 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Pins, Claws & Clips > Hair Pins
|
277 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Hair Wreaths
|
278 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Headbands
|
279 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Ponytail Holders
|
280 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Tiaras
|
281 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Wig Accessories
|
282 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Wig Accessories > Wig Caps
|
283 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Wig Accessories > Wig Glue & Tape
|
284 |
+
Apparel & Accessories > Clothing Accessories > Hair Accessories > Wigs
|
285 |
+
Apparel & Accessories > Clothing Accessories > Hand Muffs
|
286 |
+
Apparel & Accessories > Clothing Accessories > Handkerchiefs
|
287 |
+
Apparel & Accessories > Clothing Accessories > Hats
|
288 |
+
Apparel & Accessories > Clothing Accessories > Headwear
|
289 |
+
Apparel & Accessories > Clothing Accessories > Headwear > Fascinators
|
290 |
+
Apparel & Accessories > Clothing Accessories > Headwear > Headdresses
|
291 |
+
Apparel & Accessories > Clothing Accessories > Headwear > Turbans
|
292 |
+
Apparel & Accessories > Clothing Accessories > Leg Warmers
|
293 |
+
Apparel & Accessories > Clothing Accessories > Leis
|
294 |
+
Apparel & Accessories > Clothing Accessories > Maternity Belts & Support Bands
|
295 |
+
Apparel & Accessories > Clothing Accessories > Neck Gaiters
|
296 |
+
Apparel & Accessories > Clothing Accessories > Neckties
|
297 |
+
Apparel & Accessories > Clothing Accessories > Pinback Buttons
|
298 |
+
Apparel & Accessories > Clothing Accessories > Sashes
|
299 |
+
Apparel & Accessories > Clothing Accessories > Scarves & Shawls
|
300 |
+
Apparel & Accessories > Clothing Accessories > Scarves & Shawls > Scarves
|
301 |
+
Apparel & Accessories > Clothing Accessories > Scarves & Shawls > Shawls
|
302 |
+
Apparel & Accessories > Clothing Accessories > Sunglasses
|
303 |
+
Apparel & Accessories > Clothing Accessories > Suspenders
|
304 |
+
Apparel & Accessories > Clothing Accessories > Tie Clips
|
305 |
+
Apparel & Accessories > Clothing Accessories > Traditional Clothing Accessories
|
306 |
+
Apparel & Accessories > Clothing Accessories > Traditional Clothing Accessories > Obis
|
307 |
+
Apparel & Accessories > Clothing Accessories > Traditional Clothing Accessories > Tabi Socks
|
308 |
+
Apparel & Accessories > Clothing Accessories > Wristbands
|
309 |
+
Apparel & Accessories > Costumes & Accessories
|
310 |
+
Apparel & Accessories > Costumes & Accessories > Costume Accessories
|
311 |
+
Apparel & Accessories > Costumes & Accessories > Costume Accessories > Bald Caps
|
312 |
+
Apparel & Accessories > Costumes & Accessories > Costume Accessories > Costume Accessory Sets
|
313 |
+
Apparel & Accessories > Costumes & Accessories > Costume Accessories > Costume Capes
|
314 |
+
Apparel & Accessories > Costumes & Accessories > Costume Accessories > Costume Gloves
|
315 |
+
Apparel & Accessories > Costumes & Accessories > Costume Accessories > Costume Hats
|
316 |
+
Apparel & Accessories > Costumes & Accessories > Costume Accessories > Costume Special Effects
|
317 |
+
Apparel & Accessories > Costumes & Accessories > Costume Accessories > Costume Tobacco Products
|
318 |
+
Apparel & Accessories > Costumes & Accessories > Costume Accessories > Pretend Jewelry
|
319 |
+
Apparel & Accessories > Costumes & Accessories > Costume Shoes
|
320 |
+
Apparel & Accessories > Costumes & Accessories > Costumes
|
321 |
+
Apparel & Accessories > Costumes & Accessories > Masks
|
322 |
+
Apparel & Accessories > Handbag & Wallet Accessories
|
323 |
+
Apparel & Accessories > Handbag & Wallet Accessories > Checkbook Covers
|
324 |
+
Apparel & Accessories > Handbag & Wallet Accessories > Keychains
|
325 |
+
Apparel & Accessories > Handbag & Wallet Accessories > Lanyards
|
326 |
+
Apparel & Accessories > Handbag & Wallet Accessories > Wallet Chains
|
327 |
+
Apparel & Accessories > Handbags, Wallets & Cases
|
328 |
+
Apparel & Accessories > Handbags, Wallets & Cases > Badge & Pass Holders
|
329 |
+
Apparel & Accessories > Handbags, Wallets & Cases > Business Card Cases
|
330 |
+
Apparel & Accessories > Handbags, Wallets & Cases > Handbags
|
331 |
+
Apparel & Accessories > Handbags, Wallets & Cases > Wallets & Money Clips
|
332 |
+
Apparel & Accessories > Jewelry
|
333 |
+
Apparel & Accessories > Jewelry > Anklets
|
334 |
+
Apparel & Accessories > Jewelry > Body Jewelry
|
335 |
+
Apparel & Accessories > Jewelry > Bracelets
|
336 |
+
Apparel & Accessories > Jewelry > Brooches & Lapel Pins
|
337 |
+
Apparel & Accessories > Jewelry > Charms & Pendants
|
338 |
+
Apparel & Accessories > Jewelry > Earrings
|
339 |
+
Apparel & Accessories > Jewelry > Jewelry Sets
|
340 |
+
Apparel & Accessories > Jewelry > Necklaces
|
341 |
+
Apparel & Accessories > Jewelry > Rings
|
342 |
+
Apparel & Accessories > Jewelry > Watch Accessories
|
343 |
+
Apparel & Accessories > Jewelry > Watch Accessories > Watch Bands
|
344 |
+
Apparel & Accessories > Jewelry > Watch Accessories > Watch Stickers & Decals
|
345 |
+
Apparel & Accessories > Jewelry > Watch Accessories > Watch Winders
|
346 |
+
Apparel & Accessories > Jewelry > Watches
|
347 |
+
Apparel & Accessories > Shoe Accessories
|
348 |
+
Apparel & Accessories > Shoe Accessories > Boot Liners
|
349 |
+
Apparel & Accessories > Shoe Accessories > Gaiters
|
350 |
+
Apparel & Accessories > Shoe Accessories > Shoe Covers
|
351 |
+
Apparel & Accessories > Shoe Accessories > Shoelaces
|
352 |
+
Apparel & Accessories > Shoe Accessories > Spurs
|
353 |
+
Apparel & Accessories > Shoes
|
354 |
+
Arts & Entertainment
|
355 |
+
Arts & Entertainment > Event Tickets
|
356 |
+
Arts & Entertainment > Hobbies & Creative Arts
|
357 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts
|
358 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits
|
359 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Candle Making Kits
|
360 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Drawing & Painting Kits
|
361 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Fabric Repair Kits
|
362 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Incense Making Kits
|
363 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Jewelry Making Kits
|
364 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Mosaic Kits
|
365 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Needlecraft Kits
|
366 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Scrapbooking & Stamping Kits
|
367 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Craft Kits > Toy Craft Kits
|
368 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials
|
369 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper
|
370 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Cardstock & Scrapbooking Paper
|
371 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Cardstock & Scrapbooking Paper > Cardstock
|
372 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Cardstock & Scrapbooking Paper > Scrapbooking Paper
|
373 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Construction Paper
|
374 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Craft Foil
|
375 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Drawing & Painting Paper
|
376 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Origami Paper
|
377 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Transfer Paper
|
378 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Art & Craft Paper > Vellum Paper
|
379 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Fasteners & Closures
|
380 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Fasteners & Closures > Buttons & Snaps
|
381 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Fasteners & Closures > Clasps & Hooks
|
382 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Fasteners & Closures > Eyelets & Grommets
|
383 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Fasteners & Closures > Hook and Loop Fasteners
|
384 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Fasteners & Closures > Zipper Pulls
|
385 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Fasteners & Closures > Zippers
|
386 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze
|
387 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze > Art & Craft Paint
|
388 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze > Art Fixatives
|
389 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze > Art Ink
|
390 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze > Ceramic & Pottery Glazes
|
391 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze > Craft Dyes
|
392 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze > Ink Pads
|
393 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Paint, Ink & Glaze > Paint Mediums
|
394 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Shapes & Bases
|
395 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Shapes & Bases > Craft Foam & Styrofoam
|
396 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Shapes & Bases > Craft Wood & Shapes
|
397 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Shapes & Bases > Papier Mache Shapes
|
398 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Craft Shapes & Bases > Wreath & Floral Frames
|
399 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Adhesives & Magnets
|
400 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Adhesives & Magnets > Craft & Office Glue
|
401 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Adhesives & Magnets > Craft Magnets
|
402 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Adhesives & Magnets > Decorative Tape
|
403 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Adhesives & Magnets > Floral Tape
|
404 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Adhesives & Magnets > Fusible Tape
|
405 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Fibers
|
406 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Fibers > Jewelry & Beading Cord
|
407 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Fibers > Thread & Floss
|
408 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Fibers > Unspun Fiber
|
409 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Fibers > Yarn
|
410 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Wire
|
411 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Wire > Craft Pipe Cleaners
|
412 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Wire > Floral Wire
|
413 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Crafting Wire > Jewelry & Beading Wire
|
414 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims
|
415 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Appliques & Patches
|
416 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Beads
|
417 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Bows & Yo-Yos
|
418 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Decorative Stickers
|
419 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Elastic
|
420 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Feathers
|
421 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Jewelry Findings
|
422 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Loose Stones
|
423 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Rhinestones & Flatbacks
|
424 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Ribbons & Trim
|
425 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Sequins & Glitter
|
426 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embellishments & Trims > Sew-in Labels
|
427 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Embossing Powder
|
428 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Filling & Padding Material
|
429 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Filling & Padding Material > Batting & Stuffing
|
430 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Filling & Padding Material > Filling Pellets
|
431 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Filling & Padding Material > Pillow Forms
|
432 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Leather & Vinyl
|
433 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Pottery & Sculpting Materials
|
434 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Pottery & Sculpting Materials > Clay & Modeling Dough
|
435 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Pottery & Sculpting Materials > Clay & Modeling Dough > Clay
|
436 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Pottery & Sculpting Materials > Clay & Modeling Dough > Modeling Dough
|
437 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Pottery & Sculpting Materials > Papier Mache Mixes
|
438 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Pottery & Sculpting Materials > Plaster Gauze
|
439 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Pottery & Sculpting Materials > Pottery Slips
|
440 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Raw Candle Wax
|
441 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles
|
442 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles > Crafting Canvas
|
443 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles > Crafting Canvas > Needlecraft Canvas
|
444 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles > Crafting Canvas > Painting Canvas
|
445 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles > Crafting Canvas > Plastic Canvas
|
446 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles > Fabric
|
447 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles > Interfacing
|
448 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Textiles > Printable Fabric
|
449 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Wick Tabs
|
450 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Materials > Wicks
|
451 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories
|
452 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories > Craft Knife Blades
|
453 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories > Craft Machine Cases & Covers
|
454 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories > Sewing Machine Extension Tables
|
455 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories > Sewing Machine Feet
|
456 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories > Sewing Machine Replacement Parts
|
457 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories > Spinning Wheel Accessories
|
458 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tool Accessories > Stamp Blocks
|
459 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools
|
460 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Blocking Mats
|
461 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Blocking Wires
|
462 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Color Mixing Tools
|
463 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Color Mixing Tools > Palette Knives
|
464 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Color Mixing Tools > Palettes
|
465 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools
|
466 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Craft & Office Scissors
|
467 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Craft Cutters & Embossers
|
468 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Craft Knives
|
469 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Craft Scoring Tools
|
470 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Embossing Heat Tools
|
471 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Embossing Pens & Styluses
|
472 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Seam Rippers
|
473 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Cutting & Embossing Tools > Thread & Yarn Cutters
|
474 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Decoration Makers
|
475 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools
|
476 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Art Brushes
|
477 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Brayer Rollers
|
478 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Decorative Stamps
|
479 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Drafting Compasses
|
480 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Screen Printing Squeegees
|
481 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Stencil Machines
|
482 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Stencils & Die Cuts
|
483 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Stitch Markers & Counters
|
484 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Textile Art Gauges & Rulers
|
485 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Craft Measuring & Marking Tools > Wood Burning Tools
|
486 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Cutting Mats
|
487 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Dress Forms
|
488 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Felting Pads & Mats
|
489 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Frames, Hoops & Stretchers
|
490 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Glue Guns
|
491 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Light Boxes
|
492 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Needles & Hooks
|
493 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Needles & Hooks > Crochet Hooks
|
494 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Needles & Hooks > Hand-Sewing Needles
|
495 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Needles & Hooks > Knitting Needles
|
496 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Needles & Hooks > Latch & Locker Hooks
|
497 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Needles & Hooks > Sewing Machine Needles
|
498 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Safety Pins
|
499 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Straight Pins
|
500 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Textile Craft Machines
|
501 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Textile Craft Machines > Felting Needles & Machines
|
502 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Textile Craft Machines > Hand Looms
|
503 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Textile Craft Machines > Mechanical Looms
|
504 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Textile Craft Machines > Sewing Machines
|
505 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Textile Craft Machines > Spinning Wheels
|
506 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thimbles & Sewing Palms
|
507 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thimbles & Sewing Palms > Sewing Palms
|
508 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thimbles & Sewing Palms > Thimbles
|
509 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools
|
510 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Fiber Cards & Brushes
|
511 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Hand Spindles
|
512 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Needle Threaders
|
513 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Thread & Yarn Guides
|
514 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Thread & Yarn Spools
|
515 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Thread, Yarn & Bobbin Winders
|
516 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Weaving Beaters
|
517 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Art & Crafting Tools > Thread & Yarn Tools > Weaving Shuttles
|
518 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Craft Organization
|
519 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Craft Organization > Needle, Pin & Hook Organizers
|
520 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Craft Organization > Sewing Baskets & Kits
|
521 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Craft Organization > Thread & Yarn Organizers
|
522 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Crafting Patterns & Molds
|
523 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Crafting Patterns & Molds > Beading Patterns
|
524 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Crafting Patterns & Molds > Craft Molds
|
525 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Crafting Patterns & Molds > Felting Molds
|
526 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Crafting Patterns & Molds > Needlecraft Patterns
|
527 |
+
Arts & Entertainment > Hobbies & Creative Arts > Arts & Crafts > Crafting Patterns & Molds > Sewing Patterns
|
528 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles
|
529 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Autographs
|
530 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Coins & Currency
|
531 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Coins & Currency > Collectible Banknotes
|
532 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Coins & Currency > Collectible Coins
|
533 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Trading Cards
|
534 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Weapons
|
535 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Weapons > Collectible Guns
|
536 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Weapons > Collectible Knives
|
537 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Weapons > Collectible Swords
|
538 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Collectible Weapons > Sword Stands & Displays
|
539 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Postage Stamps
|
540 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Rocks & Fossils
|
541 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Scale Model Accessories
|
542 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Scale Models
|
543 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Seal Stamps
|
544 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles
|
545 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia
|
546 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Auto Racing Autographed Paraphernalia
|
547 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Baseball & Softball Autographed Paraphernalia
|
548 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Basketball Autographed Paraphernalia
|
549 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Boxing Autographed Paraphernalia
|
550 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Football Autographed Paraphernalia
|
551 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Hockey Autographed Paraphernalia
|
552 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Soccer Autographed Paraphernalia
|
553 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Autographed Sports Paraphernalia > Tennis Autographed Sports Paraphernalia
|
554 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Sports Fan Accessories
|
555 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Sports Fan Accessories > Auto Racing Fan Accessories
|
556 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Sports Fan Accessories > Baseball & Softball Fan Accessories
|
557 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Sports Fan Accessories > Basketball Fan Accessories
|
558 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Sports Fan Accessories > Football Fan Accessories
|
559 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Sports Fan Accessories > Hockey Fan Accessories
|
560 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Sports Fan Accessories > Soccer Fan Accessories
|
561 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Sports Collectibles > Sports Fan Accessories > Tennis Fan Accessories
|
562 |
+
Arts & Entertainment > Hobbies & Creative Arts > Collectibles > Vintage Advertisements
|
563 |
+
Arts & Entertainment > Hobbies & Creative Arts > Homebrewing & Winemaking Supplies
|
564 |
+
Arts & Entertainment > Hobbies & Creative Arts > Homebrewing & Winemaking Supplies > Beer Brewing Grains & Malts
|
565 |
+
Arts & Entertainment > Hobbies & Creative Arts > Homebrewing & Winemaking Supplies > Bottling Bottles
|
566 |
+
Arts & Entertainment > Hobbies & Creative Arts > Homebrewing & Winemaking Supplies > Homebrewing & Winemaking Kits
|
567 |
+
Arts & Entertainment > Hobbies & Creative Arts > Homebrewing & Winemaking Supplies > Wine Making
|
568 |
+
Arts & Entertainment > Hobbies & Creative Arts > Juggling
|
569 |
+
Arts & Entertainment > Hobbies & Creative Arts > Magic & Novelties
|
570 |
+
Arts & Entertainment > Hobbies & Creative Arts > Model Making
|
571 |
+
Arts & Entertainment > Hobbies & Creative Arts > Model Making > Model Rocketry
|
572 |
+
Arts & Entertainment > Hobbies & Creative Arts > Model Making > Model Train Accessories
|
573 |
+
Arts & Entertainment > Hobbies & Creative Arts > Model Making > Model Trains & Train Sets
|
574 |
+
Arts & Entertainment > Hobbies & Creative Arts > Model Making > Scale Model Kits
|
575 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories
|
576 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories
|
577 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning
|
578 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Care Kits
|
579 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Cleaners & Sanitizers
|
580 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Cleaning Tools
|
581 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Guards
|
582 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Lubricants
|
583 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Care & Cleaning > Brass Instrument Polishing Cloths
|
584 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Cases & Gigbags
|
585 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Mouthpieces
|
586 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Mutes
|
587 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Replacement Parts
|
588 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Brass Instrument Accessories > Brass Instrument Straps & Stands
|
589 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Conductor Batons
|
590 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Electronic Tuners
|
591 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Metronomes
|
592 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Music Benches & Stools
|
593 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Music Lyres & Flip Folders
|
594 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Music Stand Accessories
|
595 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Music Stand Accessories > Music Stand Bags
|
596 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Music Stand Accessories > Music Stand Lights
|
597 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Music Stand Accessories > Sheet Music Clips
|
598 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Music Stands
|
599 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifier Accessories
|
600 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifier Accessories > Musical Instrument Amplifier Cabinets
|
601 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifier Accessories > Musical Instrument Amplifier Covers & Cases
|
602 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifier Accessories > Musical Instrument Amplifier Footswitches
|
603 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifier Accessories > Musical Instrument Amplifier Knobs
|
604 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifier Accessories > Musical Instrument Amplifier Stands
|
605 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifier Accessories > Musical Instrument Amplifier Tubes
|
606 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Instrument Amplifiers
|
607 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Keyboard Accessories
|
608 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Keyboard Accessories > Musical Keyboard Bags & Cases
|
609 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Keyboard Accessories > Musical Keyboard Stands
|
610 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Musical Keyboard Accessories > Sustain Pedals
|
611 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories
|
612 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Cymbal & Drum Cases
|
613 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Cymbal & Drum Mutes
|
614 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Heads
|
615 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Keys
|
616 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Kit Hardware
|
617 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Kit Hardware > Bass Drum Beaters
|
618 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Kit Hardware > Drum Kit Mounting Hardware
|
619 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Kit Hardware > Drum Pedals
|
620 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Stick & Brush Accessories
|
621 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Stick & Brush Accessories > Drum Stick & Brush Bags & Holders
|
622 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Drum Sticks & Brushes
|
623 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Electronic Drum Modules
|
624 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Hand Percussion Accessories
|
625 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Hand Percussion Accessories > Hand Percussion Bags & Cases
|
626 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Hand Percussion Accessories > Hand Percussion Stands & Mounts
|
627 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Percussion Mallets
|
628 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Percussion Accessories > Percussion Stands
|
629 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories
|
630 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories
|
631 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Acoustic Guitar Pickups
|
632 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Capos
|
633 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Electric Guitar Pickups
|
634 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Cases & Gig Bags
|
635 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Fittings & Parts
|
636 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Humidifiers
|
637 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Picks
|
638 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Slides
|
639 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Stands
|
640 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Straps
|
641 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar String Winders
|
642 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Strings
|
643 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Guitar Accessories > Guitar Tuning Pegs
|
644 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories
|
645 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Bow Cases
|
646 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Bows
|
647 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Cases
|
648 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Fittings & Parts
|
649 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Mutes
|
650 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Pickups
|
651 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Stands
|
652 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > Orchestral String Instrument Accessories > Orchestral String Instrument Strings
|
653 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > String Instrument Care & Cleaning
|
654 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > String Instrument Care & Cleaning > Bow Rosin
|
655 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > String Instrument Care & Cleaning > String Instrument Cleaning Cloths
|
656 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > String Instrument Accessories > String Instrument Care & Cleaning > String Instrument Polish
|
657 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories
|
658 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories
|
659 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Care & Cleaning
|
660 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Care & Cleaning > Bassoon Swabs
|
661 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Cases & Gigbags
|
662 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Parts
|
663 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Parts > Bassoon Bocals
|
664 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Parts > Bassoon Small Parts
|
665 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Reeds
|
666 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Stands
|
667 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Bassoon Accessories > Bassoon Straps & Supports
|
668 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories
|
669 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Care & Cleaning
|
670 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Care & Cleaning > Clarinet Care Kits
|
671 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Care & Cleaning > Clarinet Pad Savers
|
672 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Care & Cleaning > Clarinet Swabs
|
673 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Cases & Gigbags
|
674 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Ligatures & Caps
|
675 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts
|
676 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts > Clarinet Barrels
|
677 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts > Clarinet Bells
|
678 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts > Clarinet Mouthpieces
|
679 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Parts > Clarinet Small Parts
|
680 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Pegs & Stands
|
681 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Reeds
|
682 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Clarinet Accessories > Clarinet Straps & Supports
|
683 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories
|
684 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Care & Cleaning
|
685 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Care & Cleaning > Flute Care Kits
|
686 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Care & Cleaning > Flute Cleaning Rods
|
687 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Care & Cleaning > Flute Swabs
|
688 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Cases & Gigbags
|
689 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Parts
|
690 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Parts > Flute Headjoints
|
691 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Parts > Flute Small Parts
|
692 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Flute Accessories > Flute Pegs & Stands
|
693 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Harmonica Accessories
|
694 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Harmonica Accessories > Harmonica Cases
|
695 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Harmonica Accessories > Harmonica Holders
|
696 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories
|
697 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Care & Cleaning
|
698 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Care & Cleaning > Oboe Care Kits
|
699 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Care & Cleaning > Oboe Swabs
|
700 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Cases & Gigbags
|
701 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Parts
|
702 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Parts > Oboe Small Parts
|
703 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Pegs & Stands
|
704 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Reeds
|
705 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Oboe & English Horn Accessories > Oboe Straps & Supports
|
706 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Recorder Accessories
|
707 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Recorder Accessories > Recorder Care & Cleaning
|
708 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Recorder Accessories > Recorder Cases
|
709 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Recorder Accessories > Recorder Parts
|
710 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories
|
711 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Care & Cleaning
|
712 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Care & Cleaning > Saxophone Care Kits
|
713 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Care & Cleaning > Saxophone Pad Savers
|
714 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Care & Cleaning > Saxophone Swabs
|
715 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Cases & Gigbags
|
716 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Ligatures & Caps
|
717 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Parts
|
718 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Parts > Saxophone Mouthpieces
|
719 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Parts > Saxophone Necks
|
720 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Parts > Saxophone Small Parts
|
721 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Pegs & Stands
|
722 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Reeds
|
723 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Saxophone Accessories > Saxophone Straps & Supports
|
724 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Woodwind Cork Grease
|
725 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Woodwind Polishing Cloths
|
726 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Woodwind Reed Cases
|
727 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instrument & Orchestra Accessories > Woodwind Instrument Accessories > Woodwind Reed Knives
|
728 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments
|
729 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Accordions & Concertinas
|
730 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Bagpipes
|
731 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass Instruments
|
732 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass Instruments > Alto & Baritone Horns
|
733 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass Instruments > Euphoniums
|
734 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass Instruments > French Horns
|
735 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass Instruments > Trombones
|
736 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass Instruments > Trumpets & Cornets
|
737 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Brass Instruments > Tubas
|
738 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Electronic Musical Instruments
|
739 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Electronic Musical Instruments > Audio Samplers
|
740 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Electronic Musical Instruments > MIDI Controllers
|
741 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Electronic Musical Instruments > Musical Keyboards
|
742 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Electronic Musical Instruments > Sound Synthesizers
|
743 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion
|
744 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Bass Drums
|
745 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Cymbals
|
746 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Drum Kits
|
747 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Electronic Drums
|
748 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Glockenspiels & Xylophones
|
749 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Gongs
|
750 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion
|
751 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Claves & Castanets
|
752 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Finger & Hand Cymbals
|
753 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Hand Bells & Chimes
|
754 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Hand Drums
|
755 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Hand Drums > Bongos
|
756 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Hand Drums > Cajons
|
757 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Hand Drums > Congas
|
758 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Hand Drums > Frame Drums
|
759 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Hand Drums > Goblet Drums
|
760 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Hand Drums > Tablas
|
761 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Hand Drums > Talking Drums
|
762 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Musical Blocks
|
763 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Musical Cowbells
|
764 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Musical Scrapers & Ratchets
|
765 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Musical Shakers
|
766 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Musical Triangles
|
767 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Tambourines
|
768 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hand Percussion > Vibraslaps
|
769 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Hi-Hats
|
770 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Practice Pads
|
771 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Snare Drums
|
772 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Percussion > Tom-Toms
|
773 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Pianos
|
774 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments
|
775 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments > Cellos
|
776 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments > Guitars
|
777 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments > Harps
|
778 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments > Upright Basses
|
779 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments > Violas
|
780 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > String Instruments > Violins
|
781 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds
|
782 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Bassoons
|
783 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Clarinets
|
784 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Flutes
|
785 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Flutophones
|
786 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Harmonicas
|
787 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Jew's Harps
|
788 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Melodicas
|
789 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Musical Pipes
|
790 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Oboes & English Horns
|
791 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Ocarinas
|
792 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Recorders
|
793 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Saxophones
|
794 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Tin Whistles
|
795 |
+
Arts & Entertainment > Hobbies & Creative Arts > Musical Instruments > Woodwinds > Train Whistles
|
796 |
+
Arts & Entertainment > Party & Celebration
|
797 |
+
Arts & Entertainment > Party & Celebration > Gift Giving
|
798 |
+
Arts & Entertainment > Party & Celebration > Gift Giving > Corsage & Boutonnière Pins
|
799 |
+
Arts & Entertainment > Party & Celebration > Gift Giving > Corsages & Boutonnières
|
800 |
+
Arts & Entertainment > Party & Celebration > Gift Giving > Fresh Cut Flowers
|
801 |
+
Arts & Entertainment > Party & Celebration > Gift Giving > Gift Cards & Certificates
|
802 |
+
Arts & Entertainment > Party & Celebration > Gift Giving > Gift Wrapping
|
803 |
+
Arts & Entertainment > Party & Celebration > Gift Giving > Gift Wrapping > Gift Bags
|
804 |
+
Arts & Entertainment > Party & Celebration > Gift Giving > Gift Wrapping > Gift Boxes & Tins
|
805 |
+
Arts & Entertainment > Party & Celebration > Gift Giving > Gift Wrapping > Gift Tags & Labels
|
806 |
+
Arts & Entertainment > Party & Celebration > Gift Giving > Gift Wrapping > Tissue Paper
|
807 |
+
Arts & Entertainment > Party & Celebration > Gift Giving > Gift Wrapping > Wrapping Paper
|
808 |
+
Arts & Entertainment > Party & Celebration > Gift Giving > Greeting & Note Cards
|
809 |
+
Arts & Entertainment > Party & Celebration > Party Supplies
|
810 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Advice Cards
|
811 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Balloon Kits
|
812 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Balloons
|
813 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Banners
|
814 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Birthday Candles
|
815 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Chair Sashes
|
816 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Cocktail Decorations
|
817 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Confetti
|
818 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Decorative Pom-Poms
|
819 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Drinking Games
|
820 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Drinking Games > Beer Pong
|
821 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Drinking Games > Beer Pong > Beer Pong Tables
|
822 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Drinking Straws & Stirrers
|
823 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Envelope Seals
|
824 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Event Programs
|
825 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Fireworks & Firecrackers
|
826 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Inflatable Party Decorations
|
827 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Invitations
|
828 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Noisemakers & Party Blowers
|
829 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Party Favors
|
830 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Party Favors > Wedding Favors
|
831 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Party Games
|
832 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Party Hats
|
833 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Party Streamers & Curtains
|
834 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Party Supply Kits
|
835 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Piñatas
|
836 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Place Card Holders
|
837 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Place Cards
|
838 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Response Cards
|
839 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Sparklers
|
840 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Special Occasion Card Boxes & Holders
|
841 |
+
Arts & Entertainment > Party & Celebration > Party Supplies > Spray String
|
842 |
+
Arts & Entertainment > Party & Celebration > Special Effects
|
843 |
+
Arts & Entertainment > Party & Celebration > Special Effects > Disco Balls
|
844 |
+
Arts & Entertainment > Party & Celebration > Special Effects > Fog Machines
|
845 |
+
Arts & Entertainment > Party & Celebration > Special Effects > Special Effects Controllers
|
846 |
+
Arts & Entertainment > Party & Celebration > Special Effects > Special Effects Light Stands
|
847 |
+
Arts & Entertainment > Party & Celebration > Special Effects > Special Effects Lighting
|
848 |
+
Arts & Entertainment > Party & Celebration > Trophies & Awards
|
849 |
+
Arts & Entertainment > Party & Celebration > Trophies & Awards > Award Certificates
|
850 |
+
Arts & Entertainment > Party & Celebration > Trophies & Awards > Award Pins & Medals
|
851 |
+
Arts & Entertainment > Party & Celebration > Trophies & Awards > Award Plaques
|
852 |
+
Arts & Entertainment > Party & Celebration > Trophies & Awards > Award Ribbons
|
853 |
+
Arts & Entertainment > Party & Celebration > Trophies & Awards > Trophies
|
854 |
+
Baby & Toddler
|
855 |
+
Baby & Toddler > Baby Bathing
|
856 |
+
Baby & Toddler > Baby Bathing > Baby Bathtubs & Bath Seats
|
857 |
+
Baby & Toddler > Baby Bathing > Shower Visors
|
858 |
+
Baby & Toddler > Baby Gift Sets
|
859 |
+
Baby & Toddler > Baby Health
|
860 |
+
Baby & Toddler > Baby Health > Baby Health & Grooming Kits
|
861 |
+
Baby & Toddler > Baby Health > Nasal Aspirators
|
862 |
+
Baby & Toddler > Baby Health > Pacifier Clips & Holders
|
863 |
+
Baby & Toddler > Baby Health > Pacifier Wipes
|
864 |
+
Baby & Toddler > Baby Health > Pacifiers & Teethers
|
865 |
+
Baby & Toddler > Baby Safety
|
866 |
+
Baby & Toddler > Baby Safety > Baby & Pet Gate Accessories
|
867 |
+
Baby & Toddler > Baby Safety > Baby & Pet Gates
|
868 |
+
Baby & Toddler > Baby Safety > Baby Monitors
|
869 |
+
Baby & Toddler > Baby Safety > Baby Safety Harnesses & Leashes
|
870 |
+
Baby & Toddler > Baby Safety > Baby Safety Locks & Guards
|
871 |
+
Baby & Toddler > Baby Safety > Baby Safety Rails
|
872 |
+
Baby & Toddler > Baby Toys & Activity Equipment
|
873 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Alphabet Toys
|
874 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Baby Activity Toys
|
875 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Baby Bouncers & Rockers
|
876 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Baby Jumpers & Swings
|
877 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Baby Mobile Accessories
|
878 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Baby Mobiles
|
879 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Baby Soothers
|
880 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Baby Walkers & Entertainers
|
881 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Play Mats & Gyms
|
882 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Play Mats & Gyms > Play Gyms
|
883 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Play Mats & Gyms > Play Mats
|
884 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Play Yards
|
885 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Push & Pull Toys
|
886 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Rattles
|
887 |
+
Baby & Toddler > Baby Toys & Activity Equipment > Sorting & Stacking Toys
|
888 |
+
Baby & Toddler > Baby Transport
|
889 |
+
Baby & Toddler > Baby Transport > Baby & Toddler Car Seats
|
890 |
+
Baby & Toddler > Baby Transport > Baby Carriers
|
891 |
+
Baby & Toddler > Baby Transport > Baby Strollers
|
892 |
+
Baby & Toddler > Baby Transport Accessories
|
893 |
+
Baby & Toddler > Baby Transport Accessories > Baby & Toddler Car Seat Accessories
|
894 |
+
Baby & Toddler > Baby Transport Accessories > Baby Carrier Accessories
|
895 |
+
Baby & Toddler > Baby Transport Accessories > Baby Stroller Accessories
|
896 |
+
Baby & Toddler > Baby Transport Accessories > Baby Transport Liners & Sacks
|
897 |
+
Baby & Toddler > Baby Transport Accessories > Shopping Cart & High Chair Covers
|
898 |
+
Baby & Toddler > Diapering
|
899 |
+
Baby & Toddler > Diapering > Baby Wipe Dispensers & Warmers
|
900 |
+
Baby & Toddler > Diapering > Baby Wipes
|
901 |
+
Baby & Toddler > Diapering > Changing Mat & Tray Covers
|
902 |
+
Baby & Toddler > Diapering > Changing Mats & Trays
|
903 |
+
Baby & Toddler > Diapering > Diaper Kits
|
904 |
+
Baby & Toddler > Diapering > Diaper Liners
|
905 |
+
Baby & Toddler > Diapering > Diaper Organizers
|
906 |
+
Baby & Toddler > Diapering > Diaper Pail Accessories
|
907 |
+
Baby & Toddler > Diapering > Diaper Pails
|
908 |
+
Baby & Toddler > Diapering > Diaper Rash Treatments
|
909 |
+
Baby & Toddler > Diapering > Diaper Wet Bags
|
910 |
+
Baby & Toddler > Diapering > Diapers
|
911 |
+
Baby & Toddler > Nursing & Feeding
|
912 |
+
Baby & Toddler > Nursing & Feeding > Baby & Toddler Food
|
913 |
+
Baby & Toddler > Nursing & Feeding > Baby & Toddler Food > Baby Cereal
|
914 |
+
Baby & Toddler > Nursing & Feeding > Baby & Toddler Food > Baby Drinks
|
915 |
+
Baby & Toddler > Nursing & Feeding > Baby & Toddler Food > Baby Food
|
916 |
+
Baby & Toddler > Nursing & Feeding > Baby & Toddler Food > Baby Formula
|
917 |
+
Baby & Toddler > Nursing & Feeding > Baby & Toddler Food > Baby Snacks
|
918 |
+
Baby & Toddler > Nursing & Feeding > Baby & Toddler Food > Toddler Nutrition Drinks & Shakes
|
919 |
+
Baby & Toddler > Nursing & Feeding > Baby Bottle Nipples & Liners
|
920 |
+
Baby & Toddler > Nursing & Feeding > Baby Bottle Nipples & Liners > Baby Bottle Liners
|
921 |
+
Baby & Toddler > Nursing & Feeding > Baby Bottle Nipples & Liners > Baby Bottle Nipples
|
922 |
+
Baby & Toddler > Nursing & Feeding > Baby Bottles
|
923 |
+
Baby & Toddler > Nursing & Feeding > Baby Care Timers
|
924 |
+
Baby & Toddler > Nursing & Feeding > Bibs
|
925 |
+
Baby & Toddler > Nursing & Feeding > Bottle Warmers & Sterilizers
|
926 |
+
Baby & Toddler > Nursing & Feeding > Breast Milk Storage Containers
|
927 |
+
Baby & Toddler > Nursing & Feeding > Breast Pump Accessories
|
928 |
+
Baby & Toddler > Nursing & Feeding > Breast Pumps
|
929 |
+
Baby & Toddler > Nursing & Feeding > Burp Cloths
|
930 |
+
Baby & Toddler > Nursing & Feeding > Nursing Covers
|
931 |
+
Baby & Toddler > Nursing & Feeding > Nursing Pads & Shields
|
932 |
+
Baby & Toddler > Nursing & Feeding > Nursing Pillow Covers
|
933 |
+
Baby & Toddler > Nursing & Feeding > Nursing Pillows
|
934 |
+
Baby & Toddler > Nursing & Feeding > Sippy Cups
|
935 |
+
Baby & Toddler > Potty Training
|
936 |
+
Baby & Toddler > Potty Training > Potty Seats
|
937 |
+
Baby & Toddler > Potty Training > Potty Training Kits
|
938 |
+
Baby & Toddler > Swaddling & Receiving Blankets
|
939 |
+
Baby & Toddler > Swaddling & Receiving Blankets > Receiving Blankets
|
940 |
+
Baby & Toddler > Swaddling & Receiving Blankets > Swaddling Blankets
|
941 |
+
Business & Industrial
|
942 |
+
Business & Industrial > Advertising & Marketing
|
943 |
+
Business & Industrial > Advertising & Marketing > Brochures
|
944 |
+
Business & Industrial > Advertising & Marketing > Trade Show Counters
|
945 |
+
Business & Industrial > Advertising & Marketing > Trade Show Displays
|
946 |
+
Business & Industrial > Agriculture
|
947 |
+
Business & Industrial > Agriculture > Animal Husbandry
|
948 |
+
Business & Industrial > Agriculture > Animal Husbandry > Egg Incubators
|
949 |
+
Business & Industrial > Agriculture > Animal Husbandry > Livestock Feed
|
950 |
+
Business & Industrial > Agriculture > Animal Husbandry > Livestock Feed > Cattle Feed
|
951 |
+
Business & Industrial > Agriculture > Animal Husbandry > Livestock Feed > Chicken Feed
|
952 |
+
Business & Industrial > Agriculture > Animal Husbandry > Livestock Feed > Goat & Sheep Feed
|
953 |
+
Business & Industrial > Agriculture > Animal Husbandry > Livestock Feed > Mixed Herd Feed
|
954 |
+
Business & Industrial > Agriculture > Animal Husbandry > Livestock Feed > Pig Feed
|
955 |
+
Business & Industrial > Agriculture > Animal Husbandry > Livestock Feeders & Waterers
|
956 |
+
Business & Industrial > Agriculture > Animal Husbandry > Livestock Halters
|
957 |
+
Business & Industrial > Automation Control Components
|
958 |
+
Business & Industrial > Automation Control Components > Programmable Logic Controllers
|
959 |
+
Business & Industrial > Automation Control Components > Variable Frequency & Adjustable Speed Drives
|
960 |
+
Business & Industrial > Construction
|
961 |
+
Business & Industrial > Construction > Surveying
|
962 |
+
Business & Industrial > Construction > Traffic Cones & Barrels
|
963 |
+
Business & Industrial > Dentistry
|
964 |
+
Business & Industrial > Dentistry > Dental Cement
|
965 |
+
Business & Industrial > Dentistry > Dental Tools
|
966 |
+
Business & Industrial > Dentistry > Dental Tools > Dappen Dishes
|
967 |
+
Business & Industrial > Dentistry > Dental Tools > Dental Mirrors
|
968 |
+
Business & Industrial > Dentistry > Dental Tools > Dental Tool Sets
|
969 |
+
Business & Industrial > Dentistry > Dental Tools > Prophy Cups
|
970 |
+
Business & Industrial > Dentistry > Dental Tools > Prophy Heads
|
971 |
+
Business & Industrial > Dentistry > Prophy Paste
|
972 |
+
Business & Industrial > Film & Television
|
973 |
+
Business & Industrial > Finance & Insurance
|
974 |
+
Business & Industrial > Finance & Insurance > Bullion
|
975 |
+
Business & Industrial > Food Service
|
976 |
+
Business & Industrial > Food Service > Bakery Boxes
|
977 |
+
Business & Industrial > Food Service > Bus Tubs
|
978 |
+
Business & Industrial > Food Service > Check Presenters
|
979 |
+
Business & Industrial > Food Service > Concession Food Containers
|
980 |
+
Business & Industrial > Food Service > Disposable Lids
|
981 |
+
Business & Industrial > Food Service > Disposable Serveware
|
982 |
+
Business & Industrial > Food Service > Disposable Serveware > Disposable Serving Trays
|
983 |
+
Business & Industrial > Food Service > Disposable Tableware
|
984 |
+
Business & Industrial > Food Service > Disposable Tableware > Disposable Bowls
|
985 |
+
Business & Industrial > Food Service > Disposable Tableware > Disposable Cups
|
986 |
+
Business & Industrial > Food Service > Disposable Tableware > Disposable Cutlery
|
987 |
+
Business & Industrial > Food Service > Disposable Tableware > Disposable Plates
|
988 |
+
Business & Industrial > Food Service > Food Service Baskets
|
989 |
+
Business & Industrial > Food Service > Food Service Carts
|
990 |
+
Business & Industrial > Food Service > Food Washers & Dryers
|
991 |
+
Business & Industrial > Food Service > Hot Dog Rollers
|
992 |
+
Business & Industrial > Food Service > Ice Bins
|
993 |
+
Business & Industrial > Food Service > Plate & Dish Warmers
|
994 |
+
Business & Industrial > Food Service > Sneeze Guards
|
995 |
+
Business & Industrial > Food Service > Take-Out Containers
|
996 |
+
Business & Industrial > Food Service > Tilt Skillets
|
997 |
+
Business & Industrial > Food Service > Vending Machines
|
998 |
+
Business & Industrial > Forestry & Logging
|
999 |
+
Business & Industrial > Hairdressing & Cosmetology
|
1000 |
+
Business & Industrial > Hairdressing & Cosmetology > Hairdressing Capes & Neck Covers
|
1001 |
+
Business & Industrial > Hairdressing & Cosmetology > Pedicure Chairs
|
1002 |
+
Business & Industrial > Hairdressing & Cosmetology > Salon Chairs
|
1003 |
+
Business & Industrial > Heavy Machinery
|
1004 |
+
Business & Industrial > Heavy Machinery > Chippers
|
1005 |
+
Business & Industrial > Hotel & Hospitality
|
1006 |
+
Business & Industrial > Industrial Storage
|
1007 |
+
Business & Industrial > Industrial Storage > Industrial Cabinets
|
1008 |
+
Business & Industrial > Industrial Storage > Industrial Shelving
|
1009 |
+
Business & Industrial > Industrial Storage > Shipping Containers
|
1010 |
+
Business & Industrial > Industrial Storage > Wire Partitions, Enclosures & Doors
|
1011 |
+
Business & Industrial > Industrial Storage Accessories
|
1012 |
+
Business & Industrial > Janitorial Carts & Caddies
|
1013 |
+
Business & Industrial > Law Enforcement
|
1014 |
+
Business & Industrial > Law Enforcement > Cuffs
|
1015 |
+
Business & Industrial > Law Enforcement > Metal Detectors
|
1016 |
+
Business & Industrial > Manufacturing
|
1017 |
+
Business & Industrial > Material Handling
|
1018 |
+
Business & Industrial > Material Handling > Conveyors
|
1019 |
+
Business & Industrial > Material Handling > Lifts & Hoists
|
1020 |
+
Business & Industrial > Material Handling > Lifts & Hoists > Hoists, Cranes & Trolleys
|
1021 |
+
Business & Industrial > Material Handling > Lifts & Hoists > Jacks & Lift Trucks
|
1022 |
+
Business & Industrial > Material Handling > Lifts & Hoists > Personnel Lifts
|
1023 |
+
Business & Industrial > Material Handling > Lifts & Hoists > Pulleys, Blocks & Sheaves
|
1024 |
+
Business & Industrial > Material Handling > Lifts & Hoists > Winches
|
1025 |
+
Business & Industrial > Material Handling > Pallets & Loading Platforms
|
1026 |
+
Business & Industrial > Medical
|
1027 |
+
Business & Industrial > Medical > Hospital Curtains
|
1028 |
+
Business & Industrial > Medical > Hospital Gowns
|
1029 |
+
Business & Industrial > Medical > Medical Bedding
|
1030 |
+
Business & Industrial > Medical > Medical Equipment
|
1031 |
+
Business & Industrial > Medical > Medical Equipment > Automated External Defibrillators
|
1032 |
+
Business & Industrial > Medical > Medical Equipment > Gait Belts
|
1033 |
+
Business & Industrial > Medical > Medical Equipment > Medical Reflex Hammers & Tuning Forks
|
1034 |
+
Business & Industrial > Medical > Medical Equipment > Medical Stretchers & Gurneys
|
1035 |
+
Business & Industrial > Medical > Medical Equipment > Otoscopes & Ophthalmoscopes
|
1036 |
+
Business & Industrial > Medical > Medical Equipment > Patient Lifts
|
1037 |
+
Business & Industrial > Medical > Medical Equipment > Stethoscopes
|
1038 |
+
Business & Industrial > Medical > Medical Equipment > Vital Signs Monitor Accessories
|
1039 |
+
Business & Industrial > Medical > Medical Equipment > Vital Signs Monitors
|
1040 |
+
Business & Industrial > Medical > Medical Furniture
|
1041 |
+
Business & Industrial > Medical > Medical Furniture > Chiropractic Tables
|
1042 |
+
Business & Industrial > Medical > Medical Furniture > Examination Chairs & Tables
|
1043 |
+
Business & Industrial > Medical > Medical Furniture > Homecare & Hospital Beds
|
1044 |
+
Business & Industrial > Medical > Medical Furniture > Medical Cabinets
|
1045 |
+
Business & Industrial > Medical > Medical Furniture > Medical Carts
|
1046 |
+
Business & Industrial > Medical > Medical Furniture > Medical Carts > Crash Carts
|
1047 |
+
Business & Industrial > Medical > Medical Furniture > Medical Carts > IV Poles & Carts
|
1048 |
+
Business & Industrial > Medical > Medical Furniture > Surgical Tables
|
1049 |
+
Business & Industrial > Medical > Medical Instruments
|
1050 |
+
Business & Industrial > Medical > Medical Instruments > Medical Forceps
|
1051 |
+
Business & Industrial > Medical > Medical Instruments > Scalpel Blades
|
1052 |
+
Business & Industrial > Medical > Medical Instruments > Scalpels
|
1053 |
+
Business & Industrial > Medical > Medical Instruments > Surgical Needles & Sutures
|
1054 |
+
Business & Industrial > Medical > Medical Supplies
|
1055 |
+
Business & Industrial > Medical > Medical Supplies > Disposable Gloves
|
1056 |
+
Business & Industrial > Medical > Medical Supplies > Finger Cots
|
1057 |
+
Business & Industrial > Medical > Medical Supplies > Medical Needles & Syringes
|
1058 |
+
Business & Industrial > Medical > Medical Supplies > Medical Needles & Syringes > Medical Needle & Syringe Sets
|
1059 |
+
Business & Industrial > Medical > Medical Supplies > Medical Needles & Syringes > Medical Needles
|
1060 |
+
Business & Industrial > Medical > Medical Supplies > Medical Needles & Syringes > Medical Syringes
|
1061 |
+
Business & Industrial > Medical > Medical Supplies > Ostomy Supplies
|
1062 |
+
Business & Industrial > Medical > Medical Supplies > Tongue Depressors
|
1063 |
+
Business & Industrial > Medical > Medical Teaching Equipment
|
1064 |
+
Business & Industrial > Medical > Medical Teaching Equipment > Medical & Emergency Response Training Mannequins
|
1065 |
+
Business & Industrial > Medical > Scrub Caps
|
1066 |
+
Business & Industrial > Medical > Scrubs
|
1067 |
+
Business & Industrial > Medical > Surgical Gowns
|
1068 |
+
Business & Industrial > Mining & Quarrying
|
1069 |
+
Business & Industrial > Piercing & Tattooing
|
1070 |
+
Business & Industrial > Piercing & Tattooing > Piercing Supplies
|
1071 |
+
Business & Industrial > Piercing & Tattooing > Piercing Supplies > Piercing Needles
|
1072 |
+
Business & Industrial > Piercing & Tattooing > Tattooing Supplies
|
1073 |
+
Business & Industrial > Piercing & Tattooing > Tattooing Supplies > Tattoo Cover-Ups
|
1074 |
+
Business & Industrial > Piercing & Tattooing > Tattooing Supplies > Tattooing Inks
|
1075 |
+
Business & Industrial > Piercing & Tattooing > Tattooing Supplies > Tattooing Machines
|
1076 |
+
Business & Industrial > Piercing & Tattooing > Tattooing Supplies > Tattooing Needles
|
1077 |
+
Business & Industrial > Retail
|
1078 |
+
Business & Industrial > Retail > Clothing Display Racks
|
1079 |
+
Business & Industrial > Retail > Display Mannequins
|
1080 |
+
Business & Industrial > Retail > Mannequin Parts
|
1081 |
+
Business & Industrial > Retail > Money Handling
|
1082 |
+
Business & Industrial > Retail > Money Handling > Banknote Verifiers
|
1083 |
+
Business & Industrial > Retail > Money Handling > Cash Register & POS Terminal Accessories
|
1084 |
+
Business & Industrial > Retail > Money Handling > Cash Register & POS Terminal Accessories > Cash Drawers & Trays
|
1085 |
+
Business & Industrial > Retail > Money Handling > Cash Register & POS Terminal Accessories > Credit Card Terminals
|
1086 |
+
Business & Industrial > Retail > Money Handling > Cash Register & POS Terminal Accessories > Signature Capture Pads
|
1087 |
+
Business & Industrial > Retail > Money Handling > Cash Registers & POS Terminals
|
1088 |
+
Business & Industrial > Retail > Money Handling > Cash Registers & POS Terminals > Cash Registers
|
1089 |
+
Business & Industrial > Retail > Money Handling > Cash Registers & POS Terminals > POS Terminals
|
1090 |
+
Business & Industrial > Retail > Money Handling > Coin & Bill Counters
|
1091 |
+
Business & Industrial > Retail > Money Handling > Money Changers
|
1092 |
+
Business & Industrial > Retail > Money Handling > Money Deposit Bags
|
1093 |
+
Business & Industrial > Retail > Money Handling > Paper Coin Wrappers & Bill Straps
|
1094 |
+
Business & Industrial > Retail > Paper & Plastic Shopping Bags
|
1095 |
+
Business & Industrial > Retail > Pricing Guns
|
1096 |
+
Business & Industrial > Retail > Retail Display Cases
|
1097 |
+
Business & Industrial > Retail > Retail Display Props & Models
|
1098 |
+
Business & Industrial > Science & Laboratory
|
1099 |
+
Business & Industrial > Science & Laboratory > Biochemicals
|
1100 |
+
Business & Industrial > Science & Laboratory > Dissection Kits
|
1101 |
+
Business & Industrial > Science & Laboratory > Laboratory Chemicals
|
1102 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment
|
1103 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Autoclaves
|
1104 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Centrifuges
|
1105 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Dry Ice Makers
|
1106 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Freeze-Drying Machines
|
1107 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Laboratory Blenders
|
1108 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Laboratory Freezers
|
1109 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Laboratory Funnels
|
1110 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Laboratory Hot Plates
|
1111 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Laboratory Ovens
|
1112 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Microscope Accessories
|
1113 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Microscope Accessories > Microscope Cameras
|
1114 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Microscope Accessories > Microscope Eyepieces & Adapters
|
1115 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Microscope Accessories > Microscope Objective Lenses
|
1116 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Microscope Accessories > Microscope Replacement Bulbs
|
1117 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Microscope Accessories > Microscope Slides
|
1118 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Microscopes
|
1119 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Microtomes
|
1120 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Spectrometer Accessories
|
1121 |
+
Business & Industrial > Science & Laboratory > Laboratory Equipment > Spectrometers
|
1122 |
+
Business & Industrial > Science & Laboratory > Laboratory Specimens
|
1123 |
+
Business & Industrial > Science & Laboratory > Laboratory Supplies
|
1124 |
+
Business & Industrial > Science & Laboratory > Laboratory Supplies > Beakers
|
1125 |
+
Business & Industrial > Science & Laboratory > Laboratory Supplies > Graduated Cylinders
|
1126 |
+
Business & Industrial > Science & Laboratory > Laboratory Supplies > Laboratory Flasks
|
1127 |
+
Business & Industrial > Science & Laboratory > Laboratory Supplies > Petri Dishes
|
1128 |
+
Business & Industrial > Science & Laboratory > Laboratory Supplies > Pipettes
|
1129 |
+
Business & Industrial > Science & Laboratory > Laboratory Supplies > Test Tube Racks
|
1130 |
+
Business & Industrial > Science & Laboratory > Laboratory Supplies > Test Tubes
|
1131 |
+
Business & Industrial > Science & Laboratory > Laboratory Supplies > Wash Bottles
|
1132 |
+
Business & Industrial > Signage
|
1133 |
+
Business & Industrial > Signage > Business Hour Signs
|
1134 |
+
Business & Industrial > Signage > Digital Signs
|
1135 |
+
Business & Industrial > Signage > Electric Signs
|
1136 |
+
Business & Industrial > Signage > Electric Signs > LED Signs
|
1137 |
+
Business & Industrial > Signage > Electric Signs > Neon Signs
|
1138 |
+
Business & Industrial > Signage > Emergency & Exit Signs
|
1139 |
+
Business & Industrial > Signage > Facility Identification Signs
|
1140 |
+
Business & Industrial > Signage > Open & Closed Signs
|
1141 |
+
Business & Industrial > Signage > Parking Signs & Permits
|
1142 |
+
Business & Industrial > Signage > Policy Signs
|
1143 |
+
Business & Industrial > Signage > Retail & Sale Signs
|
1144 |
+
Business & Industrial > Signage > Road & Traffic Signs
|
1145 |
+
Business & Industrial > Signage > Safety & Warning Signs
|
1146 |
+
Business & Industrial > Signage > Security Signs
|
1147 |
+
Business & Industrial > Signage > Sidewalk & Yard Signs
|
1148 |
+
Business & Industrial > Work Safety Protective Gear
|
1149 |
+
Business & Industrial > Work Safety Protective Gear > Bullet Proof Vests
|
1150 |
+
Business & Industrial > Work Safety Protective Gear > Gas Mask & Respirator Accessories
|
1151 |
+
Business & Industrial > Work Safety Protective Gear > Hardhats
|
1152 |
+
Business & Industrial > Work Safety Protective Gear > Hazardous Material Suits
|
1153 |
+
Business & Industrial > Work Safety Protective Gear > Protective Aprons
|
1154 |
+
Business & Industrial > Work Safety Protective Gear > Protective Eyewear
|
1155 |
+
Business & Industrial > Work Safety Protective Gear > Protective Masks
|
1156 |
+
Business & Industrial > Work Safety Protective Gear > Protective Masks > Dust Masks
|
1157 |
+
Business & Industrial > Work Safety Protective Gear > Protective Masks > Fireman's Masks
|
1158 |
+
Business & Industrial > Work Safety Protective Gear > Protective Masks > Gas Masks & Respirators
|
1159 |
+
Business & Industrial > Work Safety Protective Gear > Protective Masks > Medical Masks
|
1160 |
+
Business & Industrial > Work Safety Protective Gear > Safety Gloves
|
1161 |
+
Business & Industrial > Work Safety Protective Gear > Safety Knee Pads
|
1162 |
+
Business & Industrial > Work Safety Protective Gear > Welding Helmets
|
1163 |
+
Business & Industrial > Work Safety Protective Gear > Work Safety Harnesses
|
1164 |
+
Business & Industrial > Work Safety Protective Gear > Work Safety Tethers
|
1165 |
+
Cameras & Optics
|
1166 |
+
Cameras & Optics > Camera & Optic Accessories
|
1167 |
+
Cameras & Optics > Camera & Optic Accessories > Camera & Optic Replacement Cables
|
1168 |
+
Cameras & Optics > Camera & Optic Accessories > Camera & Video Camera Lenses
|
1169 |
+
Cameras & Optics > Camera & Optic Accessories > Camera & Video Camera Lenses > Camera Lenses
|
1170 |
+
Cameras & Optics > Camera & Optic Accessories > Camera & Video Camera Lenses > Surveillance Camera Lenses
|
1171 |
+
Cameras & Optics > Camera & Optic Accessories > Camera & Video Camera Lenses > Video Camera Lenses
|
1172 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Lens Accessories
|
1173 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Lens Accessories > Lens & Filter Adapter Rings
|
1174 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Lens Accessories > Lens Bags
|
1175 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Lens Accessories > Lens Caps
|
1176 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Lens Accessories > Lens Converters
|
1177 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Lens Accessories > Lens Filters
|
1178 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Lens Accessories > Lens Hoods
|
1179 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories
|
1180 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Accessory Sets
|
1181 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Bags & Cases
|
1182 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Body Replacement Panels & Doors
|
1183 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Digital Backs
|
1184 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Film
|
1185 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Flash Accessories
|
1186 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Flashes
|
1187 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Focus Devices
|
1188 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Gears
|
1189 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Grips
|
1190 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Image Sensors
|
1191 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Lens Zoom Units
|
1192 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Remote Controls
|
1193 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Replacement Buttons & Knobs
|
1194 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Replacement Screens & Displays
|
1195 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Silencers & Sound Blimps
|
1196 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Stabilizers & Supports
|
1197 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Straps
|
1198 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Camera Sun Hoods & Viewfinder Attachments
|
1199 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Flash Brackets
|
1200 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > On-Camera Monitors
|
1201 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Surveillance Camera Accessories
|
1202 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Underwater Camera Housing Accessories
|
1203 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Underwater Camera Housings
|
1204 |
+
Cameras & Optics > Camera & Optic Accessories > Camera Parts & Accessories > Video Camera Lights
|
1205 |
+
Cameras & Optics > Camera & Optic Accessories > Optic Accessories
|
1206 |
+
Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Binocular & Monocular Accessories
|
1207 |
+
Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Optics Bags & Cases
|
1208 |
+
Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Rangefinder Accessories
|
1209 |
+
Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Spotting Scope Accessories
|
1210 |
+
Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Telescope Accessories
|
1211 |
+
Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Thermal Optic Accessories
|
1212 |
+
Cameras & Optics > Camera & Optic Accessories > Optic Accessories > Weapon Scope & Sight Accessories
|
1213 |
+
Cameras & Optics > Camera & Optic Accessories > Tripod & Monopod Accessories
|
1214 |
+
Cameras & Optics > Camera & Optic Accessories > Tripod & Monopod Accessories > Tripod & Monopod Cases
|
1215 |
+
Cameras & Optics > Camera & Optic Accessories > Tripod & Monopod Accessories > Tripod & Monopod Heads
|
1216 |
+
Cameras & Optics > Camera & Optic Accessories > Tripod & Monopod Accessories > Tripod Collars & Mounts
|
1217 |
+
Cameras & Optics > Camera & Optic Accessories > Tripod & Monopod Accessories > Tripod Handles
|
1218 |
+
Cameras & Optics > Camera & Optic Accessories > Tripod & Monopod Accessories > Tripod Spreaders
|
1219 |
+
Cameras & Optics > Camera & Optic Accessories > Tripods & Monopods
|
1220 |
+
Cameras & Optics > Cameras
|
1221 |
+
Cameras & Optics > Cameras > Borescopes
|
1222 |
+
Cameras & Optics > Cameras > Digital Cameras
|
1223 |
+
Cameras & Optics > Cameras > Disposable Cameras
|
1224 |
+
Cameras & Optics > Cameras > Film Cameras
|
1225 |
+
Cameras & Optics > Cameras > Surveillance Cameras
|
1226 |
+
Cameras & Optics > Cameras > Trail Cameras
|
1227 |
+
Cameras & Optics > Cameras > Video Cameras
|
1228 |
+
Cameras & Optics > Cameras > Webcams
|
1229 |
+
Cameras & Optics > Optics
|
1230 |
+
Cameras & Optics > Optics > Binoculars
|
1231 |
+
Cameras & Optics > Optics > Monoculars
|
1232 |
+
Cameras & Optics > Optics > Rangefinders
|
1233 |
+
Cameras & Optics > Optics > Scopes
|
1234 |
+
Cameras & Optics > Optics > Scopes > Spotting Scopes
|
1235 |
+
Cameras & Optics > Optics > Scopes > Telescopes
|
1236 |
+
Cameras & Optics > Optics > Scopes > Weapon Scopes & Sights
|
1237 |
+
Cameras & Optics > Photography
|
1238 |
+
Cameras & Optics > Photography > Darkroom
|
1239 |
+
Cameras & Optics > Photography > Darkroom > Developing & Processing Equipment
|
1240 |
+
Cameras & Optics > Photography > Darkroom > Developing & Processing Equipment > Copystands
|
1241 |
+
Cameras & Optics > Photography > Darkroom > Developing & Processing Equipment > Darkroom Sinks
|
1242 |
+
Cameras & Optics > Photography > Darkroom > Developing & Processing Equipment > Developing Tanks & Reels
|
1243 |
+
Cameras & Optics > Photography > Darkroom > Developing & Processing Equipment > Print Trays, Washers & Dryers
|
1244 |
+
Cameras & Optics > Photography > Darkroom > Developing & Processing Equipment > Retouching Equipment & Supplies
|
1245 |
+
Cameras & Optics > Photography > Darkroom > Enlarging Equipment
|
1246 |
+
Cameras & Optics > Photography > Darkroom > Enlarging Equipment > Darkroom Easels
|
1247 |
+
Cameras & Optics > Photography > Darkroom > Enlarging Equipment > Darkroom Timers
|
1248 |
+
Cameras & Optics > Photography > Darkroom > Enlarging Equipment > Focusing Aids
|
1249 |
+
Cameras & Optics > Photography > Darkroom > Enlarging Equipment > Photographic Analyzers
|
1250 |
+
Cameras & Optics > Photography > Darkroom > Enlarging Equipment > Photographic Enlargers
|
1251 |
+
Cameras & Optics > Photography > Darkroom > Photographic Chemicals
|
1252 |
+
Cameras & Optics > Photography > Darkroom > Photographic Paper
|
1253 |
+
Cameras & Optics > Photography > Darkroom > Safelights
|
1254 |
+
Cameras & Optics > Photography > Lighting & Studio
|
1255 |
+
Cameras & Optics > Photography > Lighting & Studio > Light Meter Accessories
|
1256 |
+
Cameras & Optics > Photography > Lighting & Studio > Light Meters
|
1257 |
+
Cameras & Optics > Photography > Lighting & Studio > Studio Backgrounds
|
1258 |
+
Cameras & Optics > Photography > Lighting & Studio > Studio Light & Flash Accessories
|
1259 |
+
Cameras & Optics > Photography > Lighting & Studio > Studio Lighting Controls
|
1260 |
+
Cameras & Optics > Photography > Lighting & Studio > Studio Lighting Controls > Flash Diffusers
|
1261 |
+
Cameras & Optics > Photography > Lighting & Studio > Studio Lighting Controls > Flash Reflectors
|
1262 |
+
Cameras & Optics > Photography > Lighting & Studio > Studio Lighting Controls > Lighting Filters & Gobos
|
1263 |
+
Cameras & Optics > Photography > Lighting & Studio > Studio Lighting Controls > Softboxes
|
1264 |
+
Cameras & Optics > Photography > Lighting & Studio > Studio Lights & Flashes
|
1265 |
+
Cameras & Optics > Photography > Lighting & Studio > Studio Stand & Mount Accessories
|
1266 |
+
Cameras & Optics > Photography > Lighting & Studio > Studio Stands & Mounts
|
1267 |
+
Cameras & Optics > Photography > Photo Mounting Supplies
|
1268 |
+
Cameras & Optics > Photography > Photo Negative & Slide Storage
|
1269 |
+
Electronics
|
1270 |
+
Electronics > Arcade Equipment
|
1271 |
+
Electronics > Arcade Equipment > Basketball Arcade Games
|
1272 |
+
Electronics > Arcade Equipment > Pinball Machine Accessories
|
1273 |
+
Electronics > Arcade Equipment > Pinball Machines
|
1274 |
+
Electronics > Arcade Equipment > Skee-Ball Machines
|
1275 |
+
Electronics > Arcade Equipment > Video Game Arcade Cabinet Accessories
|
1276 |
+
Electronics > Arcade Equipment > Video Game Arcade Cabinets
|
1277 |
+
Electronics > Audio
|
1278 |
+
Electronics > Audio > Audio Accessories
|
1279 |
+
Electronics > Audio > Audio Accessories > Audio & Video Receiver Accessories
|
1280 |
+
Electronics > Audio > Audio Accessories > Headphone & Headset Accessories
|
1281 |
+
Electronics > Audio > Audio Accessories > Headphone & Headset Accessories > Headphone Cushions & Tips
|
1282 |
+
Electronics > Audio > Audio Accessories > Karaoke System Accessories
|
1283 |
+
Electronics > Audio > Audio Accessories > Karaoke System Accessories > Karaoke Chips
|
1284 |
+
Electronics > Audio > Audio Accessories > MP3 Player Accessories
|
1285 |
+
Electronics > Audio > Audio Accessories > MP3 Player Accessories > MP3 Player & Mobile Phone Accessory Sets
|
1286 |
+
Electronics > Audio > Audio Accessories > MP3 Player Accessories > MP3 Player Cases
|
1287 |
+
Electronics > Audio > Audio Accessories > Microphone Accessories
|
1288 |
+
Electronics > Audio > Audio Accessories > Microphone Stands
|
1289 |
+
Electronics > Audio > Audio Accessories > Satellite Radio Accessories
|
1290 |
+
Electronics > Audio > Audio Accessories > Speaker Accessories
|
1291 |
+
Electronics > Audio > Audio Accessories > Speaker Accessories > Speaker Bags, Covers & Cases
|
1292 |
+
Electronics > Audio > Audio Accessories > Speaker Accessories > Speaker Components & Kits
|
1293 |
+
Electronics > Audio > Audio Accessories > Speaker Accessories > Speaker Stand Bags
|
1294 |
+
Electronics > Audio > Audio Accessories > Speaker Accessories > Speaker Stands & Mounts
|
1295 |
+
Electronics > Audio > Audio Accessories > Speaker Accessories > Tactile Transducers
|
1296 |
+
Electronics > Audio > Audio Accessories > Turntable Accessories
|
1297 |
+
Electronics > Audio > Audio Components
|
1298 |
+
Electronics > Audio > Audio Components > Audio & Video Receivers
|
1299 |
+
Electronics > Audio > Audio Components > Audio Amplifiers
|
1300 |
+
Electronics > Audio > Audio Components > Audio Amplifiers > Headphone Amplifiers
|
1301 |
+
Electronics > Audio > Audio Components > Audio Amplifiers > Power Amplifiers
|
1302 |
+
Electronics > Audio > Audio Components > Audio Mixers
|
1303 |
+
Electronics > Audio > Audio Components > Audio Transmitters
|
1304 |
+
Electronics > Audio > Audio Components > Audio Transmitters > Bluetooth Transmitters
|
1305 |
+
Electronics > Audio > Audio Components > Audio Transmitters > FM Transmitters
|
1306 |
+
Electronics > Audio > Audio Components > Channel Strips
|
1307 |
+
Electronics > Audio > Audio Components > Direct Boxes
|
1308 |
+
Electronics > Audio > Audio Components > Headphones & Headsets
|
1309 |
+
Electronics > Audio > Audio Components > Headphones & Headsets > Headphones
|
1310 |
+
Electronics > Audio > Audio Components > Headphones & Headsets > Headsets
|
1311 |
+
Electronics > Audio > Audio Components > Microphones
|
1312 |
+
Electronics > Audio > Audio Components > Signal Processors
|
1313 |
+
Electronics > Audio > Audio Components > Signal Processors > Crossovers
|
1314 |
+
Electronics > Audio > Audio Components > Signal Processors > Effects Processors
|
1315 |
+
Electronics > Audio > Audio Components > Signal Processors > Equalizers
|
1316 |
+
Electronics > Audio > Audio Components > Signal Processors > Loudspeaker Management Systems
|
1317 |
+
Electronics > Audio > Audio Components > Signal Processors > Microphone Preamps
|
1318 |
+
Electronics > Audio > Audio Components > Signal Processors > Noise Gates & Compressors
|
1319 |
+
Electronics > Audio > Audio Components > Signal Processors > Phono Preamps
|
1320 |
+
Electronics > Audio > Audio Components > Speakers
|
1321 |
+
Electronics > Audio > Audio Components > Studio Recording Bundles
|
1322 |
+
Electronics > Audio > Audio Players & Recorders
|
1323 |
+
Electronics > Audio > Audio Players & Recorders > Boomboxes
|
1324 |
+
Electronics > Audio > Audio Players & Recorders > CD Players & Recorders
|
1325 |
+
Electronics > Audio > Audio Players & Recorders > Cassette Players & Recorders
|
1326 |
+
Electronics > Audio > Audio Players & Recorders > Home Theater Systems
|
1327 |
+
Electronics > Audio > Audio Players & Recorders > Jukeboxes
|
1328 |
+
Electronics > Audio > Audio Players & Recorders > Karaoke Systems
|
1329 |
+
Electronics > Audio > Audio Players & Recorders > MP3 Players
|
1330 |
+
Electronics > Audio > Audio Players & Recorders > MiniDisc Players & Recorders
|
1331 |
+
Electronics > Audio > Audio Players & Recorders > Multitrack Recorders
|
1332 |
+
Electronics > Audio > Audio Players & Recorders > Radios
|
1333 |
+
Electronics > Audio > Audio Players & Recorders > Reel-to-Reel Tape Players & Recorders
|
1334 |
+
Electronics > Audio > Audio Players & Recorders > Stereo Systems
|
1335 |
+
Electronics > Audio > Audio Players & Recorders > Turntables & Record Players
|
1336 |
+
Electronics > Audio > Audio Players & Recorders > Voice Recorders
|
1337 |
+
Electronics > Audio > Bullhorns
|
1338 |
+
Electronics > Audio > DJ & Specialty Audio
|
1339 |
+
Electronics > Audio > DJ & Specialty Audio > DJ CD Players
|
1340 |
+
Electronics > Audio > DJ & Specialty Audio > DJ Systems
|
1341 |
+
Electronics > Audio > Public Address Systems
|
1342 |
+
Electronics > Audio > Stage Equipment
|
1343 |
+
Electronics > Audio > Stage Equipment > Wireless Transmitters
|
1344 |
+
Electronics > Circuit Boards & Components
|
1345 |
+
Electronics > Circuit Boards & Components > Circuit Board Accessories
|
1346 |
+
Electronics > Circuit Boards & Components > Circuit Decoders & Encoders
|
1347 |
+
Electronics > Circuit Boards & Components > Circuit Prototyping
|
1348 |
+
Electronics > Circuit Boards & Components > Circuit Prototyping > Breadboards
|
1349 |
+
Electronics > Circuit Boards & Components > Electronic Filters
|
1350 |
+
Electronics > Circuit Boards & Components > Passive Circuit Components
|
1351 |
+
Electronics > Circuit Boards & Components > Passive Circuit Components > Capacitors
|
1352 |
+
Electronics > Circuit Boards & Components > Passive Circuit Components > Electronic Oscillators
|
1353 |
+
Electronics > Circuit Boards & Components > Passive Circuit Components > Inductors
|
1354 |
+
Electronics > Circuit Boards & Components > Passive Circuit Components > Resistors
|
1355 |
+
Electronics > Circuit Boards & Components > Printed Circuit Boards
|
1356 |
+
Electronics > Circuit Boards & Components > Printed Circuit Boards > Camera Circuit Boards
|
1357 |
+
Electronics > Circuit Boards & Components > Printed Circuit Boards > Computer Circuit Boards
|
1358 |
+
Electronics > Circuit Boards & Components > Printed Circuit Boards > Computer Circuit Boards > Computer Inverter Boards
|
1359 |
+
Electronics > Circuit Boards & Components > Printed Circuit Boards > Computer Circuit Boards > Hard Drive Circuit Boards
|
1360 |
+
Electronics > Circuit Boards & Components > Printed Circuit Boards > Computer Circuit Boards > Motherboards
|
1361 |
+
Electronics > Circuit Boards & Components > Printed Circuit Boards > Development Boards
|
1362 |
+
Electronics > Circuit Boards & Components > Printed Circuit Boards > Exercise Machine Circuit Boards
|
1363 |
+
Electronics > Circuit Boards & Components > Printed Circuit Boards > Household Appliance Circuit Boards
|
1364 |
+
Electronics > Circuit Boards & Components > Printed Circuit Boards > Pool & Spa Circuit Boards
|
1365 |
+
Electronics > Circuit Boards & Components > Printed Circuit Boards > Printer, Copier, & Fax Machine Circuit Boards
|
1366 |
+
Electronics > Circuit Boards & Components > Printed Circuit Boards > Scanner Circuit Boards
|
1367 |
+
Electronics > Circuit Boards & Components > Printed Circuit Boards > Television Circuit Boards
|
1368 |
+
Electronics > Circuit Boards & Components > Semiconductors
|
1369 |
+
Electronics > Circuit Boards & Components > Semiconductors > Diodes
|
1370 |
+
Electronics > Circuit Boards & Components > Semiconductors > Integrated Circuits & Chips
|
1371 |
+
Electronics > Circuit Boards & Components > Semiconductors > Microcontrollers
|
1372 |
+
Electronics > Circuit Boards & Components > Semiconductors > Transistors
|
1373 |
+
Electronics > Communications
|
1374 |
+
Electronics > Communications > Answering Machines
|
1375 |
+
Electronics > Communications > Caller IDs
|
1376 |
+
Electronics > Communications > Communication Radio Accessories
|
1377 |
+
Electronics > Communications > Communication Radios
|
1378 |
+
Electronics > Communications > Communication Radios > CB Radios
|
1379 |
+
Electronics > Communications > Communication Radios > Radio Scanners
|
1380 |
+
Electronics > Communications > Communication Radios > Two-Way Radios
|
1381 |
+
Electronics > Communications > Intercom Accessories
|
1382 |
+
Electronics > Communications > Intercoms
|
1383 |
+
Electronics > Communications > Pagers
|
1384 |
+
Electronics > Communications > Telephony
|
1385 |
+
Electronics > Communications > Telephony > Conference Phones
|
1386 |
+
Electronics > Communications > Telephony > Corded Phones
|
1387 |
+
Electronics > Communications > Telephony > Cordless Phones
|
1388 |
+
Electronics > Communications > Telephony > Mobile Phone Accessories
|
1389 |
+
Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Camera Accessories
|
1390 |
+
Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Cases
|
1391 |
+
Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Charms & Straps
|
1392 |
+
Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Pre-Paid Cards & SIM Cards
|
1393 |
+
Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Pre-Paid Cards & SIM Cards > Mobile Phone Pre-Paid Cards
|
1394 |
+
Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Pre-Paid Cards & SIM Cards > SIM Cards
|
1395 |
+
Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Replacement Parts
|
1396 |
+
Electronics > Communications > Telephony > Mobile Phone Accessories > Mobile Phone Stands
|
1397 |
+
Electronics > Communications > Telephony > Mobile Phone Accessories > SIM Card Ejection Tools
|
1398 |
+
Electronics > Communications > Telephony > Mobile Phones
|
1399 |
+
Electronics > Communications > Telephony > Mobile Phones > Contract Mobile Phones
|
1400 |
+
Electronics > Communications > Telephony > Mobile Phones > Pre-paid Mobile Phones
|
1401 |
+
Electronics > Communications > Telephony > Mobile Phones > Unlocked Mobile Phones
|
1402 |
+
Electronics > Communications > Telephony > Satellite Phones
|
1403 |
+
Electronics > Communications > Telephony > Telephone Accessories
|
1404 |
+
Electronics > Communications > Telephony > Telephone Accessories > Phone Cards
|
1405 |
+
Electronics > Communications > Video Conferencing
|
1406 |
+
Electronics > Components
|
1407 |
+
Electronics > Components > Accelerometers
|
1408 |
+
Electronics > Components > Converters
|
1409 |
+
Electronics > Components > Converters > Audio Converters
|
1410 |
+
Electronics > Components > Converters > Scan Converters
|
1411 |
+
Electronics > Components > Electronics Component Connectors
|
1412 |
+
Electronics > Components > Modulators
|
1413 |
+
Electronics > Components > Splitters
|
1414 |
+
Electronics > Computers
|
1415 |
+
Electronics > Computers > Barebone Computers
|
1416 |
+
Electronics > Computers > Computer Servers
|
1417 |
+
Electronics > Computers > Desktop Computers
|
1418 |
+
Electronics > Computers > Handheld Devices
|
1419 |
+
Electronics > Computers > Handheld Devices > Data Collectors
|
1420 |
+
Electronics > Computers > Handheld Devices > E-Book Readers
|
1421 |
+
Electronics > Computers > Handheld Devices > PDAs
|
1422 |
+
Electronics > Computers > Interactive Kiosks
|
1423 |
+
Electronics > Computers > Laptops
|
1424 |
+
Electronics > Computers > Smart Glasses
|
1425 |
+
Electronics > Computers > Tablet Computers
|
1426 |
+
Electronics > Computers > Thin & Zero Clients
|
1427 |
+
Electronics > Computers > Thin & Zero Clients > Thin Client Computers
|
1428 |
+
Electronics > Computers > Thin & Zero Clients > Zero Client Computers
|
1429 |
+
Electronics > Computers > Touch Table Computers
|
1430 |
+
Electronics > Electronics Accessories
|
1431 |
+
Electronics > Electronics Accessories > Adapters
|
1432 |
+
Electronics > Electronics Accessories > Adapters > Audio & Video Cable Adapters & Couplers
|
1433 |
+
Electronics > Electronics Accessories > Adapters > Memory Card Adapters
|
1434 |
+
Electronics > Electronics Accessories > Adapters > USB Adapters
|
1435 |
+
Electronics > Electronics Accessories > Antenna Accessories
|
1436 |
+
Electronics > Electronics Accessories > Antenna Accessories > Antenna Mounts & Brackets
|
1437 |
+
Electronics > Electronics Accessories > Antenna Accessories > Antenna Rotators
|
1438 |
+
Electronics > Electronics Accessories > Antenna Accessories > Satellite LNBs
|
1439 |
+
Electronics > Electronics Accessories > Antennas
|
1440 |
+
Electronics > Electronics Accessories > Audio & Video Splitters & Switches
|
1441 |
+
Electronics > Electronics Accessories > Audio & Video Splitters & Switches > DVI Splitters & Switches
|
1442 |
+
Electronics > Electronics Accessories > Audio & Video Splitters & Switches > HDMI Splitters & Switches
|
1443 |
+
Electronics > Electronics Accessories > Audio & Video Splitters & Switches > VGA Splitters & Switches
|
1444 |
+
Electronics > Electronics Accessories > Blank Media
|
1445 |
+
Electronics > Electronics Accessories > Cable Management
|
1446 |
+
Electronics > Electronics Accessories > Cable Management > Cable Clips
|
1447 |
+
Electronics > Electronics Accessories > Cable Management > Cable Tie Guns
|
1448 |
+
Electronics > Electronics Accessories > Cable Management > Cable Trays
|
1449 |
+
Electronics > Electronics Accessories > Cable Management > Patch Panels
|
1450 |
+
Electronics > Electronics Accessories > Cable Management > Wire & Cable Identification Markers
|
1451 |
+
Electronics > Electronics Accessories > Cable Management > Wire & Cable Sleeves
|
1452 |
+
Electronics > Electronics Accessories > Cable Management > Wire & Cable Ties
|
1453 |
+
Electronics > Electronics Accessories > Cables
|
1454 |
+
Electronics > Electronics Accessories > Cables > Audio & Video Cables
|
1455 |
+
Electronics > Electronics Accessories > Cables > KVM Cables
|
1456 |
+
Electronics > Electronics Accessories > Cables > Network Cables
|
1457 |
+
Electronics > Electronics Accessories > Cables > Storage & Data Transfer Cables
|
1458 |
+
Electronics > Electronics Accessories > Cables > System & Power Cables
|
1459 |
+
Electronics > Electronics Accessories > Cables > Telephone Cables
|
1460 |
+
Electronics > Electronics Accessories > Computer Accessories
|
1461 |
+
Electronics > Electronics Accessories > Computer Accessories > Computer Accessory Sets
|
1462 |
+
Electronics > Electronics Accessories > Computer Accessories > Computer Covers & Skins
|
1463 |
+
Electronics > Electronics Accessories > Computer Accessories > Computer Risers & Stands
|
1464 |
+
Electronics > Electronics Accessories > Computer Accessories > Handheld Device Accessories
|
1465 |
+
Electronics > Electronics Accessories > Computer Accessories > Handheld Device Accessories > E-Book Reader Accessories
|
1466 |
+
Electronics > Electronics Accessories > Computer Accessories > Handheld Device Accessories > E-Book Reader Accessories > E-Book Reader Cases
|
1467 |
+
Electronics > Electronics Accessories > Computer Accessories > Handheld Device Accessories > PDA Accessories
|
1468 |
+
Electronics > Electronics Accessories > Computer Accessories > Handheld Device Accessories > PDA Accessories > PDA Cases
|
1469 |
+
Electronics > Electronics Accessories > Computer Accessories > Keyboard & Mouse Wrist Rests
|
1470 |
+
Electronics > Electronics Accessories > Computer Accessories > Keyboard Trays & Platforms
|
1471 |
+
Electronics > Electronics Accessories > Computer Accessories > Laptop Docking Stations
|
1472 |
+
Electronics > Electronics Accessories > Computer Accessories > Mouse Pads
|
1473 |
+
Electronics > Electronics Accessories > Computer Accessories > Stylus Pen Nibs & Refills
|
1474 |
+
Electronics > Electronics Accessories > Computer Accessories > Stylus Pens
|
1475 |
+
Electronics > Electronics Accessories > Computer Accessories > Tablet Computer Docks & Stands
|
1476 |
+
Electronics > Electronics Accessories > Computer Components
|
1477 |
+
Electronics > Electronics Accessories > Computer Components > Blade Server Enclosures
|
1478 |
+
Electronics > Electronics Accessories > Computer Components > Computer Backplates & I/O Shields
|
1479 |
+
Electronics > Electronics Accessories > Computer Components > Computer Power Supplies
|
1480 |
+
Electronics > Electronics Accessories > Computer Components > Computer Processors
|
1481 |
+
Electronics > Electronics Accessories > Computer Components > Computer Racks & Mounts
|
1482 |
+
Electronics > Electronics Accessories > Computer Components > Computer Starter Kits
|
1483 |
+
Electronics > Electronics Accessories > Computer Components > Computer System Cooling Parts
|
1484 |
+
Electronics > Electronics Accessories > Computer Components > Desktop Computer & Server Cases
|
1485 |
+
Electronics > Electronics Accessories > Computer Components > E-Book Reader Parts
|
1486 |
+
Electronics > Electronics Accessories > Computer Components > E-Book Reader Parts > E-Book Reader Screens & Screen Digitizers
|
1487 |
+
Electronics > Electronics Accessories > Computer Components > I/O Cards & Adapters
|
1488 |
+
Electronics > Electronics Accessories > Computer Components > I/O Cards & Adapters > Audio Cards & Adapters
|
1489 |
+
Electronics > Electronics Accessories > Computer Components > I/O Cards & Adapters > Computer Interface Cards & Adapters
|
1490 |
+
Electronics > Electronics Accessories > Computer Components > I/O Cards & Adapters > Riser Cards
|
1491 |
+
Electronics > Electronics Accessories > Computer Components > I/O Cards & Adapters > TV Tuner Cards & Adapters
|
1492 |
+
Electronics > Electronics Accessories > Computer Components > I/O Cards & Adapters > Video Cards & Adapters
|
1493 |
+
Electronics > Electronics Accessories > Computer Components > Input Device Accessories
|
1494 |
+
Electronics > Electronics Accessories > Computer Components > Input Device Accessories > Barcode Scanner Stands
|
1495 |
+
Electronics > Electronics Accessories > Computer Components > Input Device Accessories > Game Controller Accessories
|
1496 |
+
Electronics > Electronics Accessories > Computer Components > Input Device Accessories > Keyboard Keys & Caps
|
1497 |
+
Electronics > Electronics Accessories > Computer Components > Input Device Accessories > Mice & Trackball Accessories
|
1498 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices
|
1499 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Barcode Scanners
|
1500 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Digital Note Taking Pens
|
1501 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Electronic Card Readers
|
1502 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Fingerprint Readers
|
1503 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Game Controllers
|
1504 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Game Controllers > Game Racing Wheels
|
1505 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Game Controllers > Game Remotes
|
1506 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Game Controllers > Gaming Pads
|
1507 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Game Controllers > Joystick Controllers
|
1508 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Game Controllers > Musical Instrument Game Controllers
|
1509 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Gesture Control Input Devices
|
1510 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Graphics Tablets
|
1511 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > KVM Switches
|
1512 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Keyboards
|
1513 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Memory Card Readers
|
1514 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Mice & Trackballs
|
1515 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Numeric Keypads
|
1516 |
+
Electronics > Electronics Accessories > Computer Components > Input Devices > Touchpads
|
1517 |
+
Electronics > Electronics Accessories > Computer Components > Laptop Parts
|
1518 |
+
Electronics > Electronics Accessories > Computer Components > Laptop Parts > Laptop Hinges
|
1519 |
+
Electronics > Electronics Accessories > Computer Components > Laptop Parts > Laptop Housings & Trim
|
1520 |
+
Electronics > Electronics Accessories > Computer Components > Laptop Parts > Laptop Replacement Cables
|
1521 |
+
Electronics > Electronics Accessories > Computer Components > Laptop Parts > Laptop Replacement Keyboards
|
1522 |
+
Electronics > Electronics Accessories > Computer Components > Laptop Parts > Laptop Replacement Screens
|
1523 |
+
Electronics > Electronics Accessories > Computer Components > Laptop Parts > Laptop Replacement Speakers
|
1524 |
+
Electronics > Electronics Accessories > Computer Components > Laptop Parts > Laptop Screen Digitizers
|
1525 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices
|
1526 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > Disk Duplicators
|
1527 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > Disk Duplicators > CD/DVD Duplicators
|
1528 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > Disk Duplicators > Hard Drive Duplicators
|
1529 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > Disk Duplicators > USB Drive Duplicators
|
1530 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > Floppy Drives
|
1531 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > Hard Drive Accessories
|
1532 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > Hard Drive Accessories > Hard Drive Carrying Cases
|
1533 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > Hard Drive Accessories > Hard Drive Docks
|
1534 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > Hard Drive Accessories > Hard Drive Enclosures & Mounts
|
1535 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > Hard Drive Arrays
|
1536 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > Hard Drives
|
1537 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > Network Storage Systems
|
1538 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > Optical Drives
|
1539 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > Tape Drives
|
1540 |
+
Electronics > Electronics Accessories > Computer Components > Storage Devices > USB Flash Drives
|
1541 |
+
Electronics > Electronics Accessories > Computer Components > Tablet Computer Parts
|
1542 |
+
Electronics > Electronics Accessories > Computer Components > Tablet Computer Parts > Tablet Computer Housings & Trim
|
1543 |
+
Electronics > Electronics Accessories > Computer Components > Tablet Computer Parts > Tablet Computer Replacement Speakers
|
1544 |
+
Electronics > Electronics Accessories > Computer Components > Tablet Computer Parts > Tablet Computer Screens & Screen Digitizers
|
1545 |
+
Electronics > Electronics Accessories > Computer Components > USB & FireWire Hubs
|
1546 |
+
Electronics > Electronics Accessories > Electronics Cleaners
|
1547 |
+
Electronics > Electronics Accessories > Electronics Films & Shields
|
1548 |
+
Electronics > Electronics Accessories > Electronics Films & Shields > Electronics Stickers & Decals
|
1549 |
+
Electronics > Electronics Accessories > Electronics Films & Shields > Keyboard Protectors
|
1550 |
+
Electronics > Electronics Accessories > Electronics Films & Shields > Privacy Filters
|
1551 |
+
Electronics > Electronics Accessories > Electronics Films & Shields > Screen Protectors
|
1552 |
+
Electronics > Electronics Accessories > Memory
|
1553 |
+
Electronics > Electronics Accessories > Memory > Cache Memory
|
1554 |
+
Electronics > Electronics Accessories > Memory > Flash Memory
|
1555 |
+
Electronics > Electronics Accessories > Memory > Flash Memory > Flash Memory Cards
|
1556 |
+
Electronics > Electronics Accessories > Memory > RAM
|
1557 |
+
Electronics > Electronics Accessories > Memory > ROM
|
1558 |
+
Electronics > Electronics Accessories > Memory > Video Memory
|
1559 |
+
Electronics > Electronics Accessories > Memory Accessories
|
1560 |
+
Electronics > Electronics Accessories > Memory Accessories > Memory Cases
|
1561 |
+
Electronics > Electronics Accessories > Mobile Phone & Tablet Tripods & Monopods
|
1562 |
+
Electronics > Electronics Accessories > Power
|
1563 |
+
Electronics > Electronics Accessories > Power > Batteries
|
1564 |
+
Electronics > Electronics Accessories > Power > Batteries > Camera Batteries
|
1565 |
+
Electronics > Electronics Accessories > Power > Batteries > Cordless Phone Batteries
|
1566 |
+
Electronics > Electronics Accessories > Power > Batteries > E-Book Reader Batteries
|
1567 |
+
Electronics > Electronics Accessories > Power > Batteries > General Purpose Batteries
|
1568 |
+
Electronics > Electronics Accessories > Power > Batteries > Laptop Batteries
|
1569 |
+
Electronics > Electronics Accessories > Power > Batteries > MP3 Player Batteries
|
1570 |
+
Electronics > Electronics Accessories > Power > Batteries > Mobile Phone Batteries
|
1571 |
+
Electronics > Electronics Accessories > Power > Batteries > PDA Batteries
|
1572 |
+
Electronics > Electronics Accessories > Power > Batteries > Tablet Computer Batteries
|
1573 |
+
Electronics > Electronics Accessories > Power > Batteries > UPS Batteries
|
1574 |
+
Electronics > Electronics Accessories > Power > Batteries > Video Camera Batteries
|
1575 |
+
Electronics > Electronics Accessories > Power > Batteries > Video Game Console & Controller Batteries
|
1576 |
+
Electronics > Electronics Accessories > Power > Battery Accessories
|
1577 |
+
Electronics > Electronics Accessories > Power > Battery Accessories > Battery Charge Controllers
|
1578 |
+
Electronics > Electronics Accessories > Power > Battery Accessories > Battery Holders
|
1579 |
+
Electronics > Electronics Accessories > Power > Battery Accessories > Camera Battery Chargers
|
1580 |
+
Electronics > Electronics Accessories > Power > Battery Accessories > General Purpose Battery Chargers
|
1581 |
+
Electronics > Electronics Accessories > Power > Battery Accessories > General Purpose Battery Testers
|
1582 |
+
Electronics > Electronics Accessories > Power > Fuel Cells
|
1583 |
+
Electronics > Electronics Accessories > Power > Power Adapter & Charger Accessories
|
1584 |
+
Electronics > Electronics Accessories > Power > Power Adapters & Chargers
|
1585 |
+
Electronics > Electronics Accessories > Power > Power Control Units
|
1586 |
+
Electronics > Electronics Accessories > Power > Power Strips & Surge Suppressors
|
1587 |
+
Electronics > Electronics Accessories > Power > Power Supply Enclosures
|
1588 |
+
Electronics > Electronics Accessories > Power > Surge Protection Devices
|
1589 |
+
Electronics > Electronics Accessories > Power > Travel Converters & Adapters
|
1590 |
+
Electronics > Electronics Accessories > Power > UPS
|
1591 |
+
Electronics > Electronics Accessories > Power > UPS Accessories
|
1592 |
+
Electronics > Electronics Accessories > Remote Controls
|
1593 |
+
Electronics > Electronics Accessories > Signal Boosters
|
1594 |
+
Electronics > Electronics Accessories > Signal Jammers
|
1595 |
+
Electronics > Electronics Accessories > Signal Jammers > GPS Jammers
|
1596 |
+
Electronics > Electronics Accessories > Signal Jammers > Mobile Phone Jammers
|
1597 |
+
Electronics > Electronics Accessories > Signal Jammers > Radar Jammers
|
1598 |
+
Electronics > GPS Accessories
|
1599 |
+
Electronics > GPS Accessories > GPS Cases
|
1600 |
+
Electronics > GPS Accessories > GPS Mounts
|
1601 |
+
Electronics > GPS Navigation Systems
|
1602 |
+
Electronics > GPS Tracking Devices
|
1603 |
+
Electronics > Marine Electronics
|
1604 |
+
Electronics > Marine Electronics > Fish Finders
|
1605 |
+
Electronics > Marine Electronics > Marine Audio & Video Receivers
|
1606 |
+
Electronics > Marine Electronics > Marine Chartplotters & GPS
|
1607 |
+
Electronics > Marine Electronics > Marine Radar
|
1608 |
+
Electronics > Marine Electronics > Marine Radios
|
1609 |
+
Electronics > Marine Electronics > Marine Speakers
|
1610 |
+
Electronics > Networking
|
1611 |
+
Electronics > Networking > Bridges & Routers
|
1612 |
+
Electronics > Networking > Bridges & Routers > Network Bridges
|
1613 |
+
Electronics > Networking > Bridges & Routers > VoIP Gateways & Routers
|
1614 |
+
Electronics > Networking > Bridges & Routers > Wireless Access Points
|
1615 |
+
Electronics > Networking > Bridges & Routers > Wireless Routers
|
1616 |
+
Electronics > Networking > Concentrators & Multiplexers
|
1617 |
+
Electronics > Networking > Hubs & Switches
|
1618 |
+
Electronics > Networking > Modem Accessories
|
1619 |
+
Electronics > Networking > Modems
|
1620 |
+
Electronics > Networking > Network Cards & Adapters
|
1621 |
+
Electronics > Networking > Network Security & Firewall Devices
|
1622 |
+
Electronics > Networking > Power Over Ethernet Adapters
|
1623 |
+
Electronics > Networking > Print Servers
|
1624 |
+
Electronics > Networking > Repeaters & Transceivers
|
1625 |
+
Electronics > Print, Copy, Scan & Fax
|
1626 |
+
Electronics > Print, Copy, Scan & Fax > 3D Printer Accessories
|
1627 |
+
Electronics > Print, Copy, Scan & Fax > 3D Printers
|
1628 |
+
Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories
|
1629 |
+
Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables
|
1630 |
+
Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables > Printer Drums & Drum Kits
|
1631 |
+
Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables > Printer Filters
|
1632 |
+
Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables > Printer Maintenance Kits
|
1633 |
+
Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables > Printer Ribbons
|
1634 |
+
Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables > Printheads
|
1635 |
+
Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables > Toner & Inkjet Cartridge Refills
|
1636 |
+
Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Consumables > Toner & Inkjet Cartridges
|
1637 |
+
Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Duplexers
|
1638 |
+
Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Memory
|
1639 |
+
Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer Stands
|
1640 |
+
Electronics > Print, Copy, Scan & Fax > Printer, Copier & Fax Machine Accessories > Printer, Copier & Fax Machine Replacement Parts
|
1641 |
+
Electronics > Print, Copy, Scan & Fax > Printers, Copiers & Fax Machines
|
1642 |
+
Electronics > Print, Copy, Scan & Fax > Scanner Accessories
|
1643 |
+
Electronics > Print, Copy, Scan & Fax > Scanners
|
1644 |
+
Electronics > Radar Detectors
|
1645 |
+
Electronics > Speed Radars
|
1646 |
+
Electronics > Toll Collection Devices
|
1647 |
+
Electronics > Video
|
1648 |
+
Electronics > Video > Computer Monitors
|
1649 |
+
Electronics > Video > Projectors
|
1650 |
+
Electronics > Video > Projectors > Multimedia Projectors
|
1651 |
+
Electronics > Video > Projectors > Overhead Projectors
|
1652 |
+
Electronics > Video > Projectors > Slide Projectors
|
1653 |
+
Electronics > Video > Satellite & Cable TV
|
1654 |
+
Electronics > Video > Satellite & Cable TV > Cable TV Receivers
|
1655 |
+
Electronics > Video > Satellite & Cable TV > Satellite Receivers
|
1656 |
+
Electronics > Video > Televisions
|
1657 |
+
Electronics > Video > Video Accessories
|
1658 |
+
Electronics > Video > Video Accessories > 3D Glasses
|
1659 |
+
Electronics > Video > Video Accessories > Computer Monitor Accessories
|
1660 |
+
Electronics > Video > Video Accessories > Computer Monitor Accessories > Color Calibrators
|
1661 |
+
Electronics > Video > Video Accessories > Projector Accessories
|
1662 |
+
Electronics > Video > Video Accessories > Projector Accessories > Projection & Tripod Skirts
|
1663 |
+
Electronics > Video > Video Accessories > Projector Accessories > Projection Screen Stands
|
1664 |
+
Electronics > Video > Video Accessories > Projector Accessories > Projection Screens
|
1665 |
+
Electronics > Video > Video Accessories > Projector Accessories > Projector Mounts
|
1666 |
+
Electronics > Video > Video Accessories > Projector Accessories > Projector Replacement Lamps
|
1667 |
+
Electronics > Video > Video Accessories > Rewinders
|
1668 |
+
Electronics > Video > Video Accessories > Television Parts & Accessories
|
1669 |
+
Electronics > Video > Video Accessories > Television Parts & Accessories > TV & Monitor Mounts
|
1670 |
+
Electronics > Video > Video Accessories > Television Parts & Accessories > TV Converter Boxes
|
1671 |
+
Electronics > Video > Video Accessories > Television Parts & Accessories > TV Replacement Lamps
|
1672 |
+
Electronics > Video > Video Accessories > Television Parts & Accessories > TV Replacement Speakers
|
1673 |
+
Electronics > Video > Video Editing Hardware & Production Equipment
|
1674 |
+
Electronics > Video > Video Multiplexers
|
1675 |
+
Electronics > Video > Video Players & Recorders
|
1676 |
+
Electronics > Video > Video Players & Recorders > DVD & Blu-ray Players
|
1677 |
+
Electronics > Video > Video Players & Recorders > DVD Recorders
|
1678 |
+
Electronics > Video > Video Players & Recorders > Digital Video Recorders
|
1679 |
+
Electronics > Video > Video Players & Recorders > Streaming & Home Media Players
|
1680 |
+
Electronics > Video > Video Players & Recorders > VCRs
|
1681 |
+
Electronics > Video > Video Servers
|
1682 |
+
Electronics > Video > Video Transmitters
|
1683 |
+
Electronics > Video Game Console Accessories
|
1684 |
+
Electronics > Video Game Console Accessories > Home Game Console Accessories
|
1685 |
+
Electronics > Video Game Console Accessories > Portable Game Console Accessories
|
1686 |
+
Electronics > Video Game Consoles
|
1687 |
+
Food, Beverages & Tobacco
|
1688 |
+
Food, Beverages & Tobacco > Beverages
|
1689 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages
|
1690 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Beer
|
1691 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Bitters
|
1692 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Cocktail Mixes
|
1693 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Cocktail Mixes > Frozen Cocktail Mixes
|
1694 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Cocktail Mixes > Shelf-stable Cocktail Mixes
|
1695 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Flavored Alcoholic Beverages
|
1696 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Hard Cider
|
1697 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits
|
1698 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Absinthe
|
1699 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Brandy
|
1700 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Gin
|
1701 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Liqueurs
|
1702 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Rum
|
1703 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Shochu & Soju
|
1704 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Shochu & Soju > Shochu
|
1705 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Shochu & Soju > Soju
|
1706 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Tequila
|
1707 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Vodka
|
1708 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Liquor & Spirits > Whiskey
|
1709 |
+
Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Wine
|
1710 |
+
Food, Beverages & Tobacco > Beverages > Buttermilk
|
1711 |
+
Food, Beverages & Tobacco > Beverages > Coffee
|
1712 |
+
Food, Beverages & Tobacco > Beverages > Eggnog
|
1713 |
+
Food, Beverages & Tobacco > Beverages > Fruit Flavored Drinks
|
1714 |
+
Food, Beverages & Tobacco > Beverages > Hot Chocolate
|
1715 |
+
Food, Beverages & Tobacco > Beverages > Juice
|
1716 |
+
Food, Beverages & Tobacco > Beverages > Milk
|
1717 |
+
Food, Beverages & Tobacco > Beverages > Non-Dairy Milk
|
1718 |
+
Food, Beverages & Tobacco > Beverages > Powdered Beverage Mixes
|
1719 |
+
Food, Beverages & Tobacco > Beverages > Soda
|
1720 |
+
Food, Beverages & Tobacco > Beverages > Sports & Energy Drinks
|
1721 |
+
Food, Beverages & Tobacco > Beverages > Tea & Infusions
|
1722 |
+
Food, Beverages & Tobacco > Beverages > Vinegar Drinks
|
1723 |
+
Food, Beverages & Tobacco > Beverages > Water
|
1724 |
+
Food, Beverages & Tobacco > Beverages > Water > Carbonated Water
|
1725 |
+
Food, Beverages & Tobacco > Beverages > Water > Carbonated Water > Flavored Carbonated Water
|
1726 |
+
Food, Beverages & Tobacco > Beverages > Water > Carbonated Water > Unflavored Carbonated Water
|
1727 |
+
Food, Beverages & Tobacco > Beverages > Water > Distilled Water
|
1728 |
+
Food, Beverages & Tobacco > Beverages > Water > Flat Mineral Water
|
1729 |
+
Food, Beverages & Tobacco > Beverages > Water > Spring Water
|
1730 |
+
Food, Beverages & Tobacco > Food Items
|
1731 |
+
Food, Beverages & Tobacco > Food Items > Bakery
|
1732 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Bagels
|
1733 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Bakery Assortments
|
1734 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Breads & Buns
|
1735 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Cakes & Dessert Bars
|
1736 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Coffee Cakes
|
1737 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Cookies
|
1738 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Cupcakes
|
1739 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Donuts
|
1740 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Fudge
|
1741 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Ice Cream Cones
|
1742 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Muffins
|
1743 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Pastries & Scones
|
1744 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Pies & Tarts
|
1745 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Taco Shells & Tostadas
|
1746 |
+
Food, Beverages & Tobacco > Food Items > Bakery > Tortillas & Wraps
|
1747 |
+
Food, Beverages & Tobacco > Food Items > Candied & Chocolate Covered Fruit
|
1748 |
+
Food, Beverages & Tobacco > Food Items > Candy & Chocolate
|
1749 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces
|
1750 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Cocktail Sauce
|
1751 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Curry Sauce
|
1752 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Dessert Toppings
|
1753 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Dessert Toppings > Fruit Toppings
|
1754 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Dessert Toppings > Ice Cream Syrup
|
1755 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Fish Sauce
|
1756 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Gravy
|
1757 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Honey
|
1758 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Horseradish Sauce
|
1759 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Hot Sauce
|
1760 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Ketchup
|
1761 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Marinades & Grilling Sauces
|
1762 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Mayonnaise
|
1763 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Mustard
|
1764 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Olives & Capers
|
1765 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Pasta Sauce
|
1766 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Pickled Fruits & Vegetables
|
1767 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Pizza Sauce
|
1768 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Relish & Chutney
|
1769 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Salad Dressing
|
1770 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Satay Sauce
|
1771 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Soy Sauce
|
1772 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Sweet and Sour Sauces
|
1773 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Syrup
|
1774 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Tahini
|
1775 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Tartar Sauce
|
1776 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > White & Cream Sauces
|
1777 |
+
Food, Beverages & Tobacco > Food Items > Condiments & Sauces > Worcestershire Sauce
|
1778 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients
|
1779 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Chips
|
1780 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Chocolate
|
1781 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Flavors & Extracts
|
1782 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Mixes
|
1783 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Powder
|
1784 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Baking Soda
|
1785 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Batter & Coating Mixes
|
1786 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Bean Paste
|
1787 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Bread Crumbs
|
1788 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Canned & Dry Milk
|
1789 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cookie Decorating Kits
|
1790 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Oils
|
1791 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Starch
|
1792 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Cooking Wine
|
1793 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Corn Syrup
|
1794 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Dough
|
1795 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Dough > Bread & Pastry Dough
|
1796 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Dough > Cookie & Brownie Dough
|
1797 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Dough > Pie Crusts
|
1798 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Edible Baking Decorations
|
1799 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Egg Replacers
|
1800 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Floss Sugar
|
1801 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Flour
|
1802 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Food Coloring
|
1803 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Frosting & Icing
|
1804 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Lemon & Lime Juice
|
1805 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Marshmallows
|
1806 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Meal
|
1807 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Molasses
|
1808 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Pie & Pastry Fillings
|
1809 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Shortening & Lard
|
1810 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Starter Cultures
|
1811 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Sugar & Sweeteners
|
1812 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Tapioca Pearls
|
1813 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Tomato Paste
|
1814 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Unflavored Gelatin
|
1815 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Vinegar
|
1816 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Waffle & Pancake Mixes
|
1817 |
+
Food, Beverages & Tobacco > Food Items > Cooking & Baking Ingredients > Yeast
|
1818 |
+
Food, Beverages & Tobacco > Food Items > Dairy Products
|
1819 |
+
Food, Beverages & Tobacco > Food Items > Dairy Products > Butter & Margarine
|
1820 |
+
Food, Beverages & Tobacco > Food Items > Dairy Products > Cheese
|
1821 |
+
Food, Beverages & Tobacco > Food Items > Dairy Products > Coffee Creamer
|
1822 |
+
Food, Beverages & Tobacco > Food Items > Dairy Products > Cottage Cheese
|
1823 |
+
Food, Beverages & Tobacco > Food Items > Dairy Products > Cream
|
1824 |
+
Food, Beverages & Tobacco > Food Items > Dairy Products > Sour Cream
|
1825 |
+
Food, Beverages & Tobacco > Food Items > Dairy Products > Whipped Cream
|
1826 |
+
Food, Beverages & Tobacco > Food Items > Dairy Products > Yogurt
|
1827 |
+
Food, Beverages & Tobacco > Food Items > Dips & Spreads
|
1828 |
+
Food, Beverages & Tobacco > Food Items > Dips & Spreads > Apple Butter
|
1829 |
+
Food, Beverages & Tobacco > Food Items > Dips & Spreads > Cheese Dips & Spreads
|
1830 |
+
Food, Beverages & Tobacco > Food Items > Dips & Spreads > Cream Cheese
|
1831 |
+
Food, Beverages & Tobacco > Food Items > Dips & Spreads > Guacamole
|
1832 |
+
Food, Beverages & Tobacco > Food Items > Dips & Spreads > Hummus
|
1833 |
+
Food, Beverages & Tobacco > Food Items > Dips & Spreads > Jams & Jellies
|
1834 |
+
Food, Beverages & Tobacco > Food Items > Dips & Spreads > Nut Butters
|
1835 |
+
Food, Beverages & Tobacco > Food Items > Dips & Spreads > Salsa
|
1836 |
+
Food, Beverages & Tobacco > Food Items > Dips & Spreads > Tapenade
|
1837 |
+
Food, Beverages & Tobacco > Food Items > Dips & Spreads > Vegetable Dip
|
1838 |
+
Food, Beverages & Tobacco > Food Items > Food Gift Baskets
|
1839 |
+
Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties
|
1840 |
+
Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties > Ice Cream & Frozen Yogurt
|
1841 |
+
Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties > Ice Cream Novelties
|
1842 |
+
Food, Beverages & Tobacco > Food Items > Frozen Desserts & Novelties > Ice Pops
|
1843 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables
|
1844 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Canned & Jarred Fruits
|
1845 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Canned & Jarred Vegetables
|
1846 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Canned & Prepared Beans
|
1847 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Dried Fruits
|
1848 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Dried Vegetables
|
1849 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Dry Beans
|
1850 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits
|
1851 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Apples
|
1852 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Atemoyas
|
1853 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Avocados
|
1854 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Babacos
|
1855 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Bananas
|
1856 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Berries
|
1857 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Breadfruit
|
1858 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Cactus Pears
|
1859 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Cherimoyas
|
1860 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits
|
1861 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits > Grapefruits
|
1862 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits > Kumquats
|
1863 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits > Lemons
|
1864 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits > Limequats
|
1865 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits > Limes
|
1866 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits > Oranges
|
1867 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Citrus Fruits > Tangelos
|
1868 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Coconuts
|
1869 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Dates
|
1870 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Feijoas
|
1871 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Figs
|
1872 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Fruit Mixes
|
1873 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Grapes
|
1874 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Guavas
|
1875 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Homely Fruits
|
1876 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Kiwis
|
1877 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Longan
|
1878 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Loquats
|
1879 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Lychees
|
1880 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Madroño
|
1881 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Mamey
|
1882 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Mangosteens
|
1883 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Melons
|
1884 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Papayas
|
1885 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Passion Fruit
|
1886 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Pears
|
1887 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Persimmons
|
1888 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Physalis
|
1889 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Pineapples
|
1890 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Pitahayas
|
1891 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Pomegranates
|
1892 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Quince
|
1893 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Rambutans
|
1894 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Sapodillo
|
1895 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Sapote
|
1896 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Soursops
|
1897 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Starfruits
|
1898 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Stone Fruits
|
1899 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Stone Fruits > Apricots
|
1900 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Stone Fruits > Cherries
|
1901 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Stone Fruits > Mangoes
|
1902 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Stone Fruits > Peaches & Nectarines
|
1903 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Stone Fruits > Plumcots
|
1904 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Stone Fruits > Plums
|
1905 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Sugar Apples
|
1906 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Fruits > Tamarindo
|
1907 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables
|
1908 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Arracachas
|
1909 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Artichokes
|
1910 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Asparagus
|
1911 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Beans
|
1912 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Beets
|
1913 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Borage
|
1914 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Broccoli
|
1915 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Brussel Sprouts
|
1916 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Cabbage
|
1917 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Cactus Leaves
|
1918 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Cardoon
|
1919 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Carrots
|
1920 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Cauliflower
|
1921 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Celery
|
1922 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Celery Roots
|
1923 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Corn
|
1924 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Cucumbers
|
1925 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Eggplants
|
1926 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Fennel Bulbs
|
1927 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Fiddlehead Ferns
|
1928 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Gai Choy
|
1929 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Gai Lan
|
1930 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Garlic
|
1931 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Ginger Root
|
1932 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Gobo Root
|
1933 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens
|
1934 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Arugula
|
1935 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Beet Greens
|
1936 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Bok Choy
|
1937 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Chard
|
1938 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Chicory
|
1939 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Choy Sum
|
1940 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Kale
|
1941 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Lettuce
|
1942 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > On Choy
|
1943 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Salad Mixes
|
1944 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Spinach
|
1945 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Greens > Yu Choy
|
1946 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Horseradish Root
|
1947 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Jicama
|
1948 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Kohlrabi
|
1949 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Leeks
|
1950 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Lotus Roots
|
1951 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Malangas
|
1952 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Mushrooms
|
1953 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Okra
|
1954 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Onions
|
1955 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Parsley Roots
|
1956 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Parsnips
|
1957 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Peas
|
1958 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Peppers
|
1959 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Potatoes
|
1960 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Radishes
|
1961 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Rhubarb
|
1962 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Shallots
|
1963 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Sprouts
|
1964 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Squashes & Gourds
|
1965 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Sugar Cane
|
1966 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Sunchokes
|
1967 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Sweet Potatoes
|
1968 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Tamarillos
|
1969 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Taro Root
|
1970 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Tomatoes
|
1971 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Turnips & Rutabagas
|
1972 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Vegetable Mixes
|
1973 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Water Chestnuts
|
1974 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Watercress
|
1975 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Wheatgrass
|
1976 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Yams
|
1977 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fresh & Frozen Vegetables > Yuca Root
|
1978 |
+
Food, Beverages & Tobacco > Food Items > Fruits & Vegetables > Fruit Sauces
|
1979 |
+
Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal
|
1980 |
+
Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Amaranth
|
1981 |
+
Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Barley
|
1982 |
+
Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Buckwheat
|
1983 |
+
Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Cereal & Granola
|
1984 |
+
Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Couscous
|
1985 |
+
Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Millet
|
1986 |
+
Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Oats, Grits & Hot Cereal
|
1987 |
+
Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Quinoa
|
1988 |
+
Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Rice
|
1989 |
+
Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Rye
|
1990 |
+
Food, Beverages & Tobacco > Food Items > Grains, Rice & Cereal > Wheat
|
1991 |
+
Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs
|
1992 |
+
Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Eggs
|
1993 |
+
Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Eggs > Egg Whites
|
1994 |
+
Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Eggs > Liquid & Frozen Eggs
|
1995 |
+
Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Eggs > Prepared Eggs
|
1996 |
+
Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Eggs > Whole Eggs
|
1997 |
+
Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Meat
|
1998 |
+
Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Meat > Canned Meats
|
1999 |
+
Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Meat > Fresh & Frozen Meats
|
2000 |
+
Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Meat > Lunch & Deli Meats
|
2001 |
+
Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Seafood
|
2002 |
+
Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Seafood > Canned Seafood
|
2003 |
+
Food, Beverages & Tobacco > Food Items > Meat, Seafood & Eggs > Seafood > Fresh & Frozen Seafood
|
2004 |
+
Food, Beverages & Tobacco > Food Items > Nuts & Seeds
|
2005 |
+
Food, Beverages & Tobacco > Food Items > Pasta & Noodles
|
2006 |
+
Food, Beverages & Tobacco > Food Items > Prepared Foods
|
2007 |
+
Food, Beverages & Tobacco > Food Items > Prepared Foods > Prepared Appetizers & Side Dishes
|
2008 |
+
Food, Beverages & Tobacco > Food Items > Prepared Foods > Prepared Meals & Entrées
|
2009 |
+
Food, Beverages & Tobacco > Food Items > Seasonings & Spices
|
2010 |
+
Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Herbs & Spices
|
2011 |
+
Food, Beverages & Tobacco > Food Items > Seasonings & Spices > MSG
|
2012 |
+
Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Pepper
|
2013 |
+
Food, Beverages & Tobacco > Food Items > Seasonings & Spices > Salt
|
2014 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods
|
2015 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Breadsticks
|
2016 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Cereal & Granola Bars
|
2017 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Cereal & Granola Bars > Cereal Bars
|
2018 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Cereal & Granola Bars > Granola Bars
|
2019 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Cheese Puffs
|
2020 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Chips
|
2021 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Crackers
|
2022 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Croutons
|
2023 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Fruit Snacks
|
2024 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Jerky
|
2025 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Popcorn
|
2026 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Pork Rinds
|
2027 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Pretzels
|
2028 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Pudding & Gelatin Snacks
|
2029 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Puffed Rice Cakes
|
2030 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Salad Toppings
|
2031 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Sesame Sticks
|
2032 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Snack Cakes
|
2033 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Sticky Rice Cakes
|
2034 |
+
Food, Beverages & Tobacco > Food Items > Snack Foods > Trail & Snack Mixes
|
2035 |
+
Food, Beverages & Tobacco > Food Items > Soups & Broths
|
2036 |
+
Food, Beverages & Tobacco > Food Items > Tofu, Soy & Vegetarian Products
|
2037 |
+
Food, Beverages & Tobacco > Food Items > Tofu, Soy & Vegetarian Products > Cheese Alternatives
|
2038 |
+
Food, Beverages & Tobacco > Food Items > Tofu, Soy & Vegetarian Products > Meat Alternatives
|
2039 |
+
Food, Beverages & Tobacco > Food Items > Tofu, Soy & Vegetarian Products > Seitan
|
2040 |
+
Food, Beverages & Tobacco > Food Items > Tofu, Soy & Vegetarian Products > Tempeh
|
2041 |
+
Food, Beverages & Tobacco > Food Items > Tofu, Soy & Vegetarian Products > Tofu
|
2042 |
+
Food, Beverages & Tobacco > Tobacco Products
|
2043 |
+
Food, Beverages & Tobacco > Tobacco Products > Chewing Tobacco
|
2044 |
+
Food, Beverages & Tobacco > Tobacco Products > Cigarettes
|
2045 |
+
Food, Beverages & Tobacco > Tobacco Products > Cigars
|
2046 |
+
Food, Beverages & Tobacco > Tobacco Products > Loose Tobacco
|
2047 |
+
Food, Beverages & Tobacco > Tobacco Products > Smoking Pipes
|
2048 |
+
Food, Beverages & Tobacco > Tobacco Products > Vaporizers & Electronic Cigarettes
|
2049 |
+
Food, Beverages & Tobacco > Tobacco Products > Vaporizers & Electronic Cigarettes > Electronic Cigarettes
|
2050 |
+
Food, Beverages & Tobacco > Tobacco Products > Vaporizers & Electronic Cigarettes > Vaporizers
|
2051 |
+
Furniture
|
2052 |
+
Furniture > Baby & Toddler Furniture
|
2053 |
+
Furniture > Baby & Toddler Furniture > Baby & Toddler Furniture Sets
|
2054 |
+
Furniture > Baby & Toddler Furniture > Bassinet & Cradle Accessories
|
2055 |
+
Furniture > Baby & Toddler Furniture > Bassinets & Cradles
|
2056 |
+
Furniture > Baby & Toddler Furniture > Changing Tables
|
2057 |
+
Furniture > Baby & Toddler Furniture > Crib & Toddler Bed Accessories
|
2058 |
+
Furniture > Baby & Toddler Furniture > Crib & Toddler Bed Accessories > Crib Bumpers & Liners
|
2059 |
+
Furniture > Baby & Toddler Furniture > Crib & Toddler Bed Accessories > Crib Conversion Kits
|
2060 |
+
Furniture > Baby & Toddler Furniture > Cribs & Toddler Beds
|
2061 |
+
Furniture > Baby & Toddler Furniture > High Chair & Booster Seat Accessories
|
2062 |
+
Furniture > Baby & Toddler Furniture > High Chairs & Booster Seats
|
2063 |
+
Furniture > Beds & Accessories
|
2064 |
+
Furniture > Beds & Accessories > Bed & Bed Frame Accessories
|
2065 |
+
Furniture > Beds & Accessories > Beds & Bed Frames
|
2066 |
+
Furniture > Beds & Accessories > Headboards & Footboards
|
2067 |
+
Furniture > Beds & Accessories > Mattress Foundations
|
2068 |
+
Furniture > Beds & Accessories > Mattresses
|
2069 |
+
Furniture > Benches
|
2070 |
+
Furniture > Benches > Kitchen & Dining Benches
|
2071 |
+
Furniture > Benches > Storage & Entryway Benches
|
2072 |
+
Furniture > Benches > Vanity Benches
|
2073 |
+
Furniture > Cabinets & Storage
|
2074 |
+
Furniture > Cabinets & Storage > Armoires & Wardrobes
|
2075 |
+
Furniture > Cabinets & Storage > Buffets & Sideboards
|
2076 |
+
Furniture > Cabinets & Storage > China Cabinets & Hutches
|
2077 |
+
Furniture > Cabinets & Storage > Dressers
|
2078 |
+
Furniture > Cabinets & Storage > File Cabinets
|
2079 |
+
Furniture > Cabinets & Storage > Ironing Centers
|
2080 |
+
Furniture > Cabinets & Storage > Kitchen Cabinets
|
2081 |
+
Furniture > Cabinets & Storage > Magazine Racks
|
2082 |
+
Furniture > Cabinets & Storage > Media Storage Cabinets & Racks
|
2083 |
+
Furniture > Cabinets & Storage > Storage Cabinets & Lockers
|
2084 |
+
Furniture > Cabinets & Storage > Storage Chests
|
2085 |
+
Furniture > Cabinets & Storage > Storage Chests > Hope Chests
|
2086 |
+
Furniture > Cabinets & Storage > Storage Chests > Toy Chests
|
2087 |
+
Furniture > Cabinets & Storage > Vanities
|
2088 |
+
Furniture > Cabinets & Storage > Vanities > Bathroom Vanities
|
2089 |
+
Furniture > Cabinets & Storage > Vanities > Bedroom Vanities
|
2090 |
+
Furniture > Cabinets & Storage > Wine & Liquor Cabinets
|
2091 |
+
Furniture > Cabinets & Storage > Wine Racks
|
2092 |
+
Furniture > Carts & Islands
|
2093 |
+
Furniture > Carts & Islands > Kitchen & Dining Carts
|
2094 |
+
Furniture > Carts & Islands > Kitchen Islands
|
2095 |
+
Furniture > Chair Accessories
|
2096 |
+
Furniture > Chair Accessories > Hanging Chair Replacement Parts
|
2097 |
+
Furniture > Chairs
|
2098 |
+
Furniture > Chairs > Arm Chairs, Recliners & Sleeper Chairs
|
2099 |
+
Furniture > Chairs > Bean Bag Chairs
|
2100 |
+
Furniture > Chairs > Chaises
|
2101 |
+
Furniture > Chairs > Electric Massaging Chairs
|
2102 |
+
Furniture > Chairs > Floor Chairs
|
2103 |
+
Furniture > Chairs > Folding Chairs & Stools
|
2104 |
+
Furniture > Chairs > Gaming Chairs
|
2105 |
+
Furniture > Chairs > Hanging Chairs
|
2106 |
+
Furniture > Chairs > Kitchen & Dining Room Chairs
|
2107 |
+
Furniture > Chairs > Rocking Chairs
|
2108 |
+
Furniture > Chairs > Slipper Chairs
|
2109 |
+
Furniture > Chairs > Table & Bar Stools
|
2110 |
+
Furniture > Entertainment Centers & TV Stands
|
2111 |
+
Furniture > Furniture Sets
|
2112 |
+
Furniture > Furniture Sets > Bathroom Furniture Sets
|
2113 |
+
Furniture > Furniture Sets > Bedroom Furniture Sets
|
2114 |
+
Furniture > Furniture Sets > Kitchen & Dining Furniture Sets
|
2115 |
+
Furniture > Furniture Sets > Living Room Furniture Sets
|
2116 |
+
Furniture > Futon Frames
|
2117 |
+
Furniture > Futon Pads
|
2118 |
+
Furniture > Futons
|
2119 |
+
Furniture > Office Furniture
|
2120 |
+
Furniture > Office Furniture > Desks
|
2121 |
+
Furniture > Office Furniture > Office Chairs
|
2122 |
+
Furniture > Office Furniture > Office Furniture Sets
|
2123 |
+
Furniture > Office Furniture > Workspace Tables
|
2124 |
+
Furniture > Office Furniture > Workspace Tables > Art & Drafting Tables
|
2125 |
+
Furniture > Office Furniture > Workspace Tables > Conference Room Tables
|
2126 |
+
Furniture > Office Furniture > Workstations & Cubicles
|
2127 |
+
Furniture > Office Furniture Accessories
|
2128 |
+
Furniture > Office Furniture Accessories > Desk Parts & Accessories
|
2129 |
+
Furniture > Office Furniture Accessories > Office Chair Accessories
|
2130 |
+
Furniture > Office Furniture Accessories > Workstation & Cubicle Accessories
|
2131 |
+
Furniture > Ottomans
|
2132 |
+
Furniture > Outdoor Furniture
|
2133 |
+
Furniture > Outdoor Furniture > Outdoor Beds
|
2134 |
+
Furniture > Outdoor Furniture > Outdoor Furniture Sets
|
2135 |
+
Furniture > Outdoor Furniture > Outdoor Ottomans
|
2136 |
+
Furniture > Outdoor Furniture > Outdoor Seating
|
2137 |
+
Furniture > Outdoor Furniture > Outdoor Seating > Outdoor Benches
|
2138 |
+
Furniture > Outdoor Furniture > Outdoor Seating > Outdoor Chairs
|
2139 |
+
Furniture > Outdoor Furniture > Outdoor Seating > Outdoor Sectional Sofa Units
|
2140 |
+
Furniture > Outdoor Furniture > Outdoor Seating > Outdoor Sofas
|
2141 |
+
Furniture > Outdoor Furniture > Outdoor Seating > Sunloungers
|
2142 |
+
Furniture > Outdoor Furniture > Outdoor Storage Boxes
|
2143 |
+
Furniture > Outdoor Furniture > Outdoor Tables
|
2144 |
+
Furniture > Outdoor Furniture Accessories
|
2145 |
+
Furniture > Outdoor Furniture Accessories > Outdoor Furniture Covers
|
2146 |
+
Furniture > Room Divider Accessories
|
2147 |
+
Furniture > Room Dividers
|
2148 |
+
Furniture > Shelving
|
2149 |
+
Furniture > Shelving > Bookcases & Standing Shelves
|
2150 |
+
Furniture > Shelving > Wall Shelves & Ledges
|
2151 |
+
Furniture > Shelving Accessories
|
2152 |
+
Furniture > Shelving Accessories > Replacement Shelves
|
2153 |
+
Furniture > Sofa Accessories
|
2154 |
+
Furniture > Sofa Accessories > Chair & Sofa Supports
|
2155 |
+
Furniture > Sofa Accessories > Sectional Sofa Units
|
2156 |
+
Furniture > Sofas
|
2157 |
+
Furniture > Table Accessories
|
2158 |
+
Furniture > Table Accessories > Table Legs
|
2159 |
+
Furniture > Table Accessories > Table Tops
|
2160 |
+
Furniture > Tables
|
2161 |
+
Furniture > Tables > Accent Tables
|
2162 |
+
Furniture > Tables > Accent Tables > Coffee Tables
|
2163 |
+
Furniture > Tables > Accent Tables > End Tables
|
2164 |
+
Furniture > Tables > Accent Tables > Sofa Tables
|
2165 |
+
Furniture > Tables > Activity Tables
|
2166 |
+
Furniture > Tables > Folding Tables
|
2167 |
+
Furniture > Tables > Kitchen & Dining Room Tables
|
2168 |
+
Furniture > Tables > Kotatsu
|
2169 |
+
Furniture > Tables > Nightstands
|
2170 |
+
Furniture > Tables > Poker & Game Tables
|
2171 |
+
Furniture > Tables > Sewing Machine Tables
|
2172 |
+
Hardware
|
2173 |
+
Hardware > Building Consumables
|
2174 |
+
Hardware > Building Consumables > Chemicals
|
2175 |
+
Hardware > Building Consumables > Chemicals > Acid Neutralizers
|
2176 |
+
Hardware > Building Consumables > Chemicals > Ammonia
|
2177 |
+
Hardware > Building Consumables > Chemicals > Chimney Cleaners
|
2178 |
+
Hardware > Building Consumables > Chemicals > Concrete & Masonry Cleaners
|
2179 |
+
Hardware > Building Consumables > Chemicals > De-icers
|
2180 |
+
Hardware > Building Consumables > Chemicals > Deck & Fence Cleaners
|
2181 |
+
Hardware > Building Consumables > Chemicals > Drain Cleaners
|
2182 |
+
Hardware > Building Consumables > Chemicals > Electrical Freeze Sprays
|
2183 |
+
Hardware > Building Consumables > Chemicals > Lighter Fluid
|
2184 |
+
Hardware > Building Consumables > Chemicals > Septic Tank & Cesspool Treatments
|
2185 |
+
Hardware > Building Consumables > Hardware Glue & Adhesives
|
2186 |
+
Hardware > Building Consumables > Hardware Tape
|
2187 |
+
Hardware > Building Consumables > Lubricants
|
2188 |
+
Hardware > Building Consumables > Masonry Consumables
|
2189 |
+
Hardware > Building Consumables > Masonry Consumables > Bricks & Concrete Blocks
|
2190 |
+
Hardware > Building Consumables > Masonry Consumables > Cement, Mortar & Concrete Mixes
|
2191 |
+
Hardware > Building Consumables > Masonry Consumables > Grout
|
2192 |
+
Hardware > Building Consumables > Painting Consumables
|
2193 |
+
Hardware > Building Consumables > Painting Consumables > Paint
|
2194 |
+
Hardware > Building Consumables > Painting Consumables > Paint Binders
|
2195 |
+
Hardware > Building Consumables > Painting Consumables > Primers
|
2196 |
+
Hardware > Building Consumables > Painting Consumables > Stains
|
2197 |
+
Hardware > Building Consumables > Painting Consumables > Varnishes & Finishes
|
2198 |
+
Hardware > Building Consumables > Plumbing Primer
|
2199 |
+
Hardware > Building Consumables > Protective Coatings & Sealants
|
2200 |
+
Hardware > Building Consumables > Solder & Flux
|
2201 |
+
Hardware > Building Consumables > Solvents, Strippers & Thinners
|
2202 |
+
Hardware > Building Consumables > Wall Patching Compounds & Plaster
|
2203 |
+
Hardware > Building Materials
|
2204 |
+
Hardware > Building Materials > Countertops
|
2205 |
+
Hardware > Building Materials > Door Hardware
|
2206 |
+
Hardware > Building Materials > Door Hardware > Door Bells & Chimes
|
2207 |
+
Hardware > Building Materials > Door Hardware > Door Closers
|
2208 |
+
Hardware > Building Materials > Door Hardware > Door Frames
|
2209 |
+
Hardware > Building Materials > Door Hardware > Door Keyhole Escutcheons
|
2210 |
+
Hardware > Building Materials > Door Hardware > Door Knobs & Handles
|
2211 |
+
Hardware > Building Materials > Door Hardware > Door Knockers
|
2212 |
+
Hardware > Building Materials > Door Hardware > Door Push Plates
|
2213 |
+
Hardware > Building Materials > Door Hardware > Door Stops
|
2214 |
+
Hardware > Building Materials > Door Hardware > Door Strikes
|
2215 |
+
Hardware > Building Materials > Doors
|
2216 |
+
Hardware > Building Materials > Doors > Garage Doors
|
2217 |
+
Hardware > Building Materials > Doors > Home Doors
|
2218 |
+
Hardware > Building Materials > Drywall
|
2219 |
+
Hardware > Building Materials > Flooring & Carpet
|
2220 |
+
Hardware > Building Materials > Glass
|
2221 |
+
Hardware > Building Materials > Handrails & Railing Systems
|
2222 |
+
Hardware > Building Materials > Hatches
|
2223 |
+
Hardware > Building Materials > Insulation
|
2224 |
+
Hardware > Building Materials > Lumber & Sheet Stock
|
2225 |
+
Hardware > Building Materials > Molding
|
2226 |
+
Hardware > Building Materials > Rebar & Remesh
|
2227 |
+
Hardware > Building Materials > Roofing
|
2228 |
+
Hardware > Building Materials > Roofing > Gutter Accessories
|
2229 |
+
Hardware > Building Materials > Roofing > Gutters
|
2230 |
+
Hardware > Building Materials > Roofing > Roof Flashings
|
2231 |
+
Hardware > Building Materials > Roofing > Roofing Shingles & Tiles
|
2232 |
+
Hardware > Building Materials > Shutters
|
2233 |
+
Hardware > Building Materials > Siding
|
2234 |
+
Hardware > Building Materials > Sound Dampening Panels & Foam
|
2235 |
+
Hardware > Building Materials > Staircases
|
2236 |
+
Hardware > Building Materials > Wall & Ceiling Tile
|
2237 |
+
Hardware > Building Materials > Wall Paneling
|
2238 |
+
Hardware > Building Materials > Weather Stripping & Weatherization Supplies
|
2239 |
+
Hardware > Building Materials > Window Hardware
|
2240 |
+
Hardware > Building Materials > Window Hardware > Window Cranks
|
2241 |
+
Hardware > Building Materials > Window Hardware > Window Frames
|
2242 |
+
Hardware > Building Materials > Windows
|
2243 |
+
Hardware > Fencing & Barriers
|
2244 |
+
Hardware > Fencing & Barriers > Fence & Gate Accessories
|
2245 |
+
Hardware > Fencing & Barriers > Fence Panels
|
2246 |
+
Hardware > Fencing & Barriers > Fence Pickets
|
2247 |
+
Hardware > Fencing & Barriers > Fence Posts & Rails
|
2248 |
+
Hardware > Fencing & Barriers > Garden Borders & Edging
|
2249 |
+
Hardware > Fencing & Barriers > Gates
|
2250 |
+
Hardware > Fencing & Barriers > Lattice
|
2251 |
+
Hardware > Fencing & Barriers > Safety & Crowd Control Barriers
|
2252 |
+
Hardware > Fuel
|
2253 |
+
Hardware > Fuel > Home Heating Oil
|
2254 |
+
Hardware > Fuel > Kerosene
|
2255 |
+
Hardware > Fuel > Kerosene > Clear Kerosene
|
2256 |
+
Hardware > Fuel > Kerosene > Dyed Kerosene
|
2257 |
+
Hardware > Fuel > Propane
|
2258 |
+
Hardware > Fuel Containers & Tanks
|
2259 |
+
Hardware > Hardware Accessories
|
2260 |
+
Hardware > Hardware Accessories > Brackets & Reinforcement Braces
|
2261 |
+
Hardware > Hardware Accessories > Cabinet Hardware
|
2262 |
+
Hardware > Hardware Accessories > Cabinet Hardware > Cabinet & Furniture Keyhole Escutcheons
|
2263 |
+
Hardware > Hardware Accessories > Cabinet Hardware > Cabinet Backplates
|
2264 |
+
Hardware > Hardware Accessories > Cabinet Hardware > Cabinet Catches
|
2265 |
+
Hardware > Hardware Accessories > Cabinet Hardware > Cabinet Doors
|
2266 |
+
Hardware > Hardware Accessories > Cabinet Hardware > Cabinet Knobs & Handles
|
2267 |
+
Hardware > Hardware Accessories > Casters
|
2268 |
+
Hardware > Hardware Accessories > Chain, Wire & Rope
|
2269 |
+
Hardware > Hardware Accessories > Chain, Wire & Rope > Bungee Cords
|
2270 |
+
Hardware > Hardware Accessories > Chain, Wire & Rope > Chains
|
2271 |
+
Hardware > Hardware Accessories > Chain, Wire & Rope > Pull Chains
|
2272 |
+
Hardware > Hardware Accessories > Chain, Wire & Rope > Ropes & Hardware Cable
|
2273 |
+
Hardware > Hardware Accessories > Chain, Wire & Rope > Tie Down Straps
|
2274 |
+
Hardware > Hardware Accessories > Chain, Wire & Rope > Twine
|
2275 |
+
Hardware > Hardware Accessories > Chain, Wire & Rope > Utility Wire
|
2276 |
+
Hardware > Hardware Accessories > Coils
|
2277 |
+
Hardware > Hardware Accessories > Concrete Molds
|
2278 |
+
Hardware > Hardware Accessories > Dowel Pins & Rods
|
2279 |
+
Hardware > Hardware Accessories > Drawer Slides
|
2280 |
+
Hardware > Hardware Accessories > Drop Cloths
|
2281 |
+
Hardware > Hardware Accessories > Filters & Screens
|
2282 |
+
Hardware > Hardware Accessories > Flagging & Caution Tape
|
2283 |
+
Hardware > Hardware Accessories > Gas Hoses
|
2284 |
+
Hardware > Hardware Accessories > Ground Spikes
|
2285 |
+
Hardware > Hardware Accessories > Hardware Fasteners
|
2286 |
+
Hardware > Hardware Accessories > Hardware Fasteners > Drywall Anchors
|
2287 |
+
Hardware > Hardware Accessories > Hardware Fasteners > Nails
|
2288 |
+
Hardware > Hardware Accessories > Hardware Fasteners > Nuts & Bolts
|
2289 |
+
Hardware > Hardware Accessories > Hardware Fasteners > Rivets
|
2290 |
+
Hardware > Hardware Accessories > Hardware Fasteners > Screw Posts
|
2291 |
+
Hardware > Hardware Accessories > Hardware Fasteners > Screws
|
2292 |
+
Hardware > Hardware Accessories > Hardware Fasteners > Threaded Rods
|
2293 |
+
Hardware > Hardware Accessories > Hardware Fasteners > Washers
|
2294 |
+
Hardware > Hardware Accessories > Hinges
|
2295 |
+
Hardware > Hardware Accessories > Hooks, Buckles & Fasteners
|
2296 |
+
Hardware > Hardware Accessories > Hooks, Buckles & Fasteners > Chain Connectors & Links
|
2297 |
+
Hardware > Hardware Accessories > Hooks, Buckles & Fasteners > Gear Ties
|
2298 |
+
Hardware > Hardware Accessories > Hooks, Buckles & Fasteners > Lifting Hooks, Clamps & Shackles
|
2299 |
+
Hardware > Hardware Accessories > Hooks, Buckles & Fasteners > Utility Buckles
|
2300 |
+
Hardware > Hardware Accessories > Lubrication Hoses
|
2301 |
+
Hardware > Hardware Accessories > Metal Casting Molds
|
2302 |
+
Hardware > Hardware Accessories > Moving & Soundproofing Blankets & Covers
|
2303 |
+
Hardware > Hardware Accessories > Pneumatic Hoses
|
2304 |
+
Hardware > Hardware Accessories > Post Base Plates
|
2305 |
+
Hardware > Hardware Accessories > Springs
|
2306 |
+
Hardware > Hardware Accessories > Tarps
|
2307 |
+
Hardware > Hardware Accessories > Tool Storage & Organization
|
2308 |
+
Hardware > Hardware Accessories > Tool Storage & Organization > Garden Hose Storage
|
2309 |
+
Hardware > Hardware Accessories > Tool Storage & Organization > Tool & Equipment Belts
|
2310 |
+
Hardware > Hardware Accessories > Tool Storage & Organization > Tool Bags
|
2311 |
+
Hardware > Hardware Accessories > Tool Storage & Organization > Tool Boxes
|
2312 |
+
Hardware > Hardware Accessories > Tool Storage & Organization > Tool Cabinets & Chests
|
2313 |
+
Hardware > Hardware Accessories > Tool Storage & Organization > Tool Organizer Liners & Inserts
|
2314 |
+
Hardware > Hardware Accessories > Tool Storage & Organization > Tool Sheaths
|
2315 |
+
Hardware > Hardware Accessories > Tool Storage & Organization > Work Benches
|
2316 |
+
Hardware > Hardware Accessories > Wall Jacks & Braces
|
2317 |
+
Hardware > Hardware Pumps
|
2318 |
+
Hardware > Hardware Pumps > Home Appliance Pumps
|
2319 |
+
Hardware > Hardware Pumps > Pool, Fountain & Pond Pumps
|
2320 |
+
Hardware > Hardware Pumps > Sprinkler, Booster & Irrigation System Pumps
|
2321 |
+
Hardware > Hardware Pumps > Sump, Sewage & Effluent Pumps
|
2322 |
+
Hardware > Hardware Pumps > Utility Pumps
|
2323 |
+
Hardware > Hardware Pumps > Well Pumps & Systems
|
2324 |
+
Hardware > Heating, Ventilation & Air Conditioning
|
2325 |
+
Hardware > Heating, Ventilation & Air Conditioning > Air & Filter Dryers
|
2326 |
+
Hardware > Heating, Ventilation & Air Conditioning > Air Ducts
|
2327 |
+
Hardware > Heating, Ventilation & Air Conditioning > HVAC Controls
|
2328 |
+
Hardware > Heating, Ventilation & Air Conditioning > HVAC Controls > Control Panels
|
2329 |
+
Hardware > Heating, Ventilation & Air Conditioning > HVAC Controls > Humidistats
|
2330 |
+
Hardware > Heating, Ventilation & Air Conditioning > HVAC Controls > Thermostats
|
2331 |
+
Hardware > Heating, Ventilation & Air Conditioning > Vents & Flues
|
2332 |
+
Hardware > Locks & Keys
|
2333 |
+
Hardware > Locks & Keys > Key Blanks
|
2334 |
+
Hardware > Locks & Keys > Key Caps
|
2335 |
+
Hardware > Locks & Keys > Key Card Entry Systems
|
2336 |
+
Hardware > Locks & Keys > Locks & Latches
|
2337 |
+
Hardware > Plumbing
|
2338 |
+
Hardware > Plumbing > Plumbing Fittings & Supports
|
2339 |
+
Hardware > Plumbing > Plumbing Fittings & Supports > Gaskets & O-Rings
|
2340 |
+
Hardware > Plumbing > Plumbing Fittings & Supports > In-Wall Carriers & Mounting Frames
|
2341 |
+
Hardware > Plumbing > Plumbing Fittings & Supports > Nozzles
|
2342 |
+
Hardware > Plumbing > Plumbing Fittings & Supports > Pipe Adapters & Bushings
|
2343 |
+
Hardware > Plumbing > Plumbing Fittings & Supports > Pipe Caps & Plugs
|
2344 |
+
Hardware > Plumbing > Plumbing Fittings & Supports > Pipe Connectors
|
2345 |
+
Hardware > Plumbing > Plumbing Fittings & Supports > Plumbing Flanges
|
2346 |
+
Hardware > Plumbing > Plumbing Fittings & Supports > Plumbing Pipe Clamps
|
2347 |
+
Hardware > Plumbing > Plumbing Fittings & Supports > Plumbing Regulators
|
2348 |
+
Hardware > Plumbing > Plumbing Fittings & Supports > Plumbing Valves
|
2349 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts
|
2350 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Bathtub Accessories
|
2351 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Bathtub Accessories > Bathtub Bases & Feet
|
2352 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Bathtub Accessories > Bathtub Skirts
|
2353 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Bathtub Accessories > Bathtub Spouts
|
2354 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components
|
2355 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components > Drain Covers & Strainers
|
2356 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components > Drain Frames
|
2357 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components > Drain Liners
|
2358 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components > Drain Openers
|
2359 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components > Drain Rods
|
2360 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components > Plumbing Traps
|
2361 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drain Components > Plumbing Wastes
|
2362 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Drains
|
2363 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Faucet Accessories
|
2364 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Faucet Accessories > Faucet Aerators
|
2365 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Faucet Accessories > Faucet Handles & Controls
|
2366 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Fixture Plates
|
2367 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts
|
2368 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Bathtub & Shower Jets
|
2369 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Electric & Power Showers
|
2370 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Shower Arms & Connectors
|
2371 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Shower Bases
|
2372 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Shower Columns
|
2373 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Shower Doors & Enclosures
|
2374 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Shower Heads
|
2375 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Shower Walls & Surrounds
|
2376 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Shower Parts > Shower Water Filters
|
2377 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Sink Accessories
|
2378 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Sink Accessories > Sink Legs
|
2379 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories
|
2380 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Ballcocks & Flappers
|
2381 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Bidet Faucets & Sprayers
|
2382 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Toilet & Bidet Seats
|
2383 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Toilet Seat Covers
|
2384 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Toilet Seat Lid Covers
|
2385 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Toilet Tank Covers
|
2386 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Toilet Tank Levers
|
2387 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Toilet Tanks
|
2388 |
+
Hardware > Plumbing > Plumbing Fixture Hardware & Parts > Toilet & Bidet Accessories > Toilet Trim
|
2389 |
+
Hardware > Plumbing > Plumbing Fixtures
|
2390 |
+
Hardware > Plumbing > Plumbing Fixtures > Bathroom Suites
|
2391 |
+
Hardware > Plumbing > Plumbing Fixtures > Bathtubs
|
2392 |
+
Hardware > Plumbing > Plumbing Fixtures > Faucets
|
2393 |
+
Hardware > Plumbing > Plumbing Fixtures > Shower Stalls & Kits
|
2394 |
+
Hardware > Plumbing > Plumbing Fixtures > Sinks
|
2395 |
+
Hardware > Plumbing > Plumbing Fixtures > Sinks > Bathroom Sinks
|
2396 |
+
Hardware > Plumbing > Plumbing Fixtures > Sinks > Kitchen & Utility Sinks
|
2397 |
+
Hardware > Plumbing > Plumbing Fixtures > Toilets & Bidets
|
2398 |
+
Hardware > Plumbing > Plumbing Fixtures > Toilets & Bidets > Bidets
|
2399 |
+
Hardware > Plumbing > Plumbing Fixtures > Toilets & Bidets > Toilets
|
2400 |
+
Hardware > Plumbing > Plumbing Fixtures > Toilets & Bidets > Urinals
|
2401 |
+
Hardware > Plumbing > Plumbing Hoses & Supply Lines
|
2402 |
+
Hardware > Plumbing > Plumbing Pipes
|
2403 |
+
Hardware > Plumbing > Plumbing Repair Kits
|
2404 |
+
Hardware > Plumbing > Water Dispensing & Filtration
|
2405 |
+
Hardware > Plumbing > Water Dispensing & Filtration > In-Line Water Filters
|
2406 |
+
Hardware > Plumbing > Water Dispensing & Filtration > Water Dispensers
|
2407 |
+
Hardware > Plumbing > Water Dispensing & Filtration > Water Dispensers > Drinking Fountains
|
2408 |
+
Hardware > Plumbing > Water Dispensing & Filtration > Water Dispensers > Water Chillers
|
2409 |
+
Hardware > Plumbing > Water Dispensing & Filtration > Water Distillers
|
2410 |
+
Hardware > Plumbing > Water Dispensing & Filtration > Water Filtration Accessories
|
2411 |
+
Hardware > Plumbing > Water Dispensing & Filtration > Water Filtration Accessories > Water Filter Cartridges
|
2412 |
+
Hardware > Plumbing > Water Dispensing & Filtration > Water Filtration Accessories > Water Filter Housings
|
2413 |
+
Hardware > Plumbing > Water Dispensing & Filtration > Water Softener Salt
|
2414 |
+
Hardware > Plumbing > Water Dispensing & Filtration > Water Softeners
|
2415 |
+
Hardware > Plumbing > Water Levelers
|
2416 |
+
Hardware > Plumbing > Water Timers
|
2417 |
+
Hardware > Plumbing > Well Supplies
|
2418 |
+
Hardware > Power & Electrical Supplies
|
2419 |
+
Hardware > Power & Electrical Supplies > Armatures, Rotors & Stators
|
2420 |
+
Hardware > Power & Electrical Supplies > Ballasts & Starters
|
2421 |
+
Hardware > Power & Electrical Supplies > Carbon Brushes
|
2422 |
+
Hardware > Power & Electrical Supplies > Circuit Breaker Panels
|
2423 |
+
Hardware > Power & Electrical Supplies > Conduit & Housings
|
2424 |
+
Hardware > Power & Electrical Supplies > Conduit & Housings > Electrical Conduit
|
2425 |
+
Hardware > Power & Electrical Supplies > Conduit & Housings > Heat-Shrink Tubing
|
2426 |
+
Hardware > Power & Electrical Supplies > Electrical Motors
|
2427 |
+
Hardware > Power & Electrical Supplies > Electrical Mount Boxes & Brackets
|
2428 |
+
Hardware > Power & Electrical Supplies > Electrical Plug Caps
|
2429 |
+
Hardware > Power & Electrical Supplies > Electrical Switches
|
2430 |
+
Hardware > Power & Electrical Supplies > Electrical Switches > Light Switches
|
2431 |
+
Hardware > Power & Electrical Supplies > Electrical Switches > Specialty Electrical Switches & Relays
|
2432 |
+
Hardware > Power & Electrical Supplies > Electrical Wires & Cable
|
2433 |
+
Hardware > Power & Electrical Supplies > Extension Cord Accessories
|
2434 |
+
Hardware > Power & Electrical Supplies > Extension Cords
|
2435 |
+
Hardware > Power & Electrical Supplies > Generator Accessories
|
2436 |
+
Hardware > Power & Electrical Supplies > Generators
|
2437 |
+
Hardware > Power & Electrical Supplies > Home Automation Kits
|
2438 |
+
Hardware > Power & Electrical Supplies > Phone & Data Jacks
|
2439 |
+
Hardware > Power & Electrical Supplies > Power Converters
|
2440 |
+
Hardware > Power & Electrical Supplies > Power Inlets
|
2441 |
+
Hardware > Power & Electrical Supplies > Power Inverters
|
2442 |
+
Hardware > Power & Electrical Supplies > Power Outlets & Sockets
|
2443 |
+
Hardware > Power & Electrical Supplies > Solar Energy Kits
|
2444 |
+
Hardware > Power & Electrical Supplies > Solar Panels
|
2445 |
+
Hardware > Power & Electrical Supplies > Voltage Transformers & Regulators
|
2446 |
+
Hardware > Power & Electrical Supplies > Wall Plates & Covers
|
2447 |
+
Hardware > Power & Electrical Supplies > Wall Socket Controls & Sensors
|
2448 |
+
Hardware > Power & Electrical Supplies > Wire Caps & Nuts
|
2449 |
+
Hardware > Power & Electrical Supplies > Wire Terminals & Connectors
|
2450 |
+
Hardware > Small Engines
|
2451 |
+
Hardware > Storage Tanks
|
2452 |
+
Hardware > Tool Accessories
|
2453 |
+
Hardware > Tool Accessories > Abrasive Blaster Accessories
|
2454 |
+
Hardware > Tool Accessories > Abrasive Blaster Accessories > Sandblasting Cabinets
|
2455 |
+
Hardware > Tool Accessories > Axe Accessories
|
2456 |
+
Hardware > Tool Accessories > Axe Accessories > Axe Handles
|
2457 |
+
Hardware > Tool Accessories > Axe Accessories > Axe Heads
|
2458 |
+
Hardware > Tool Accessories > Cutter Accessories
|
2459 |
+
Hardware > Tool Accessories > Cutter Accessories > Nibbler Dies
|
2460 |
+
Hardware > Tool Accessories > Drill & Screwdriver Accessories
|
2461 |
+
Hardware > Tool Accessories > Drill & Screwdriver Accessories > Drill & Screwdriver Bits
|
2462 |
+
Hardware > Tool Accessories > Drill & Screwdriver Accessories > Drill Bit Extensions
|
2463 |
+
Hardware > Tool Accessories > Drill & Screwdriver Accessories > Drill Bit Sharpeners
|
2464 |
+
Hardware > Tool Accessories > Drill & Screwdriver Accessories > Drill Chucks
|
2465 |
+
Hardware > Tool Accessories > Drill & Screwdriver Accessories > Drill Stands & Guides
|
2466 |
+
Hardware > Tool Accessories > Drill & Screwdriver Accessories > Hole Saws
|
2467 |
+
Hardware > Tool Accessories > Driver Accessories
|
2468 |
+
Hardware > Tool Accessories > Flashlight Accessories
|
2469 |
+
Hardware > Tool Accessories > Grinder Accessories
|
2470 |
+
Hardware > Tool Accessories > Grinder Accessories > Grinding Wheels & Points
|
2471 |
+
Hardware > Tool Accessories > Hammer Accessories
|
2472 |
+
Hardware > Tool Accessories > Hammer Accessories > Air Hammer Accessories
|
2473 |
+
Hardware > Tool Accessories > Hammer Accessories > Hammer Handles
|
2474 |
+
Hardware > Tool Accessories > Hammer Accessories > Hammer Heads
|
2475 |
+
Hardware > Tool Accessories > Industrial Staples
|
2476 |
+
Hardware > Tool Accessories > Jigs
|
2477 |
+
Hardware > Tool Accessories > Magnetizers & Demagnetizers
|
2478 |
+
Hardware > Tool Accessories > Mattock & Pickaxe Accessories
|
2479 |
+
Hardware > Tool Accessories > Mattock & Pickaxe Accessories > Mattock & Pickaxe Handles
|
2480 |
+
Hardware > Tool Accessories > Measuring Tool & Sensor Accessories
|
2481 |
+
Hardware > Tool Accessories > Measuring Tool & Sensor Accessories > Electrical Testing Tool Accessories
|
2482 |
+
Hardware > Tool Accessories > Measuring Tool & Sensor Accessories > Gas Detector Accessories
|
2483 |
+
Hardware > Tool Accessories > Measuring Tool & Sensor Accessories > Measuring Scale Accessories
|
2484 |
+
Hardware > Tool Accessories > Measuring Tool & Sensor Accessories > Multimeter Accessories
|
2485 |
+
Hardware > Tool Accessories > Mixing Tool Paddles
|
2486 |
+
Hardware > Tool Accessories > Paint Tool Accessories
|
2487 |
+
Hardware > Tool Accessories > Paint Tool Accessories > Airbrush Accessories
|
2488 |
+
Hardware > Tool Accessories > Paint Tool Accessories > Paint Brush Cleaning Solutions
|
2489 |
+
Hardware > Tool Accessories > Paint Tool Accessories > Paint Roller Accessories
|
2490 |
+
Hardware > Tool Accessories > Power Tool Batteries
|
2491 |
+
Hardware > Tool Accessories > Power Tool Chargers
|
2492 |
+
Hardware > Tool Accessories > Router Accessories
|
2493 |
+
Hardware > Tool Accessories > Router Accessories > Router Bits
|
2494 |
+
Hardware > Tool Accessories > Router Accessories > Router Tables
|
2495 |
+
Hardware > Tool Accessories > Sanding Accessories
|
2496 |
+
Hardware > Tool Accessories > Sanding Accessories > Sandpaper & Sanding Sponges
|
2497 |
+
Hardware > Tool Accessories > Saw Accessories
|
2498 |
+
Hardware > Tool Accessories > Saw Accessories > Band Saw Accessories
|
2499 |
+
Hardware > Tool Accessories > Saw Accessories > Handheld Circular Saw Accessories
|
2500 |
+
Hardware > Tool Accessories > Saw Accessories > Jigsaw Accessories
|
2501 |
+
Hardware > Tool Accessories > Saw Accessories > Miter Saw Accessories
|
2502 |
+
Hardware > Tool Accessories > Saw Accessories > Table Saw Accessories
|
2503 |
+
Hardware > Tool Accessories > Shaper Accessories
|
2504 |
+
Hardware > Tool Accessories > Shaper Accessories > Shaper Cutters
|
2505 |
+
Hardware > Tool Accessories > Soldering Iron Accessories
|
2506 |
+
Hardware > Tool Accessories > Soldering Iron Accessories > Soldering Iron Stands
|
2507 |
+
Hardware > Tool Accessories > Soldering Iron Accessories > Soldering Iron Tips
|
2508 |
+
Hardware > Tool Accessories > Tool Blades
|
2509 |
+
Hardware > Tool Accessories > Tool Blades > Cutter & Scraper Blades
|
2510 |
+
Hardware > Tool Accessories > Tool Blades > Saw Blades
|
2511 |
+
Hardware > Tool Accessories > Tool Handle Wedges
|
2512 |
+
Hardware > Tool Accessories > Tool Safety Tethers
|
2513 |
+
Hardware > Tool Accessories > Tool Sockets
|
2514 |
+
Hardware > Tool Accessories > Tool Stands
|
2515 |
+
Hardware > Tool Accessories > Tool Stands > Saw Stands
|
2516 |
+
Hardware > Tool Accessories > Wedge Tools
|
2517 |
+
Hardware > Tool Accessories > Welding Accessories
|
2518 |
+
Hardware > Tools
|
2519 |
+
Hardware > Tools > Abrasive Blasters
|
2520 |
+
Hardware > Tools > Anvils
|
2521 |
+
Hardware > Tools > Axes
|
2522 |
+
Hardware > Tools > Carpentry Jointers
|
2523 |
+
Hardware > Tools > Carving Chisels & Gouges
|
2524 |
+
Hardware > Tools > Caulking Tools
|
2525 |
+
Hardware > Tools > Chimney Brushes
|
2526 |
+
Hardware > Tools > Compactors
|
2527 |
+
Hardware > Tools > Compressors
|
2528 |
+
Hardware > Tools > Concrete Brooms
|
2529 |
+
Hardware > Tools > Cutters
|
2530 |
+
Hardware > Tools > Cutters > Bolt Cutters
|
2531 |
+
Hardware > Tools > Cutters > Glass Cutters
|
2532 |
+
Hardware > Tools > Cutters > Handheld Metal Shears & Nibblers
|
2533 |
+
Hardware > Tools > Cutters > Nippers
|
2534 |
+
Hardware > Tools > Cutters > Pipe Cutters
|
2535 |
+
Hardware > Tools > Cutters > Rebar Cutters
|
2536 |
+
Hardware > Tools > Cutters > Tile & Shingle Cutters
|
2537 |
+
Hardware > Tools > Cutters > Utility Knives
|
2538 |
+
Hardware > Tools > Deburrers
|
2539 |
+
Hardware > Tools > Dollies & Hand Trucks
|
2540 |
+
Hardware > Tools > Drills
|
2541 |
+
Hardware > Tools > Drills > Augers
|
2542 |
+
Hardware > Tools > Drills > Drill Presses
|
2543 |
+
Hardware > Tools > Drills > Handheld Power Drills
|
2544 |
+
Hardware > Tools > Drills > Mortisers
|
2545 |
+
Hardware > Tools > Drills > Pneumatic Drills
|
2546 |
+
Hardware > Tools > Electrician Fish Tape
|
2547 |
+
Hardware > Tools > Flashlights & Headlamps
|
2548 |
+
Hardware > Tools > Flashlights & Headlamps > Flashlights
|
2549 |
+
Hardware > Tools > Flashlights & Headlamps > Headlamps
|
2550 |
+
Hardware > Tools > Grease Guns
|
2551 |
+
Hardware > Tools > Grinders
|
2552 |
+
Hardware > Tools > Grips
|
2553 |
+
Hardware > Tools > Hammers
|
2554 |
+
Hardware > Tools > Hammers > Manual Hammers
|
2555 |
+
Hardware > Tools > Hammers > Powered Hammers
|
2556 |
+
Hardware > Tools > Handheld Power Mixers
|
2557 |
+
Hardware > Tools > Hardware Torches
|
2558 |
+
Hardware > Tools > Heat Guns
|
2559 |
+
Hardware > Tools > Impact Wrenches & Drivers
|
2560 |
+
Hardware > Tools > Industrial Vibrators
|
2561 |
+
Hardware > Tools > Inspection Mirrors
|
2562 |
+
Hardware > Tools > Ladders & Scaffolding
|
2563 |
+
Hardware > Tools > Ladders & Scaffolding > Ladder Carts
|
2564 |
+
Hardware > Tools > Ladders & Scaffolding > Ladders
|
2565 |
+
Hardware > Tools > Ladders & Scaffolding > Scaffolding
|
2566 |
+
Hardware > Tools > Ladders & Scaffolding > Step Stools
|
2567 |
+
Hardware > Tools > Ladders & Scaffolding > Work Platforms
|
2568 |
+
Hardware > Tools > Lathes
|
2569 |
+
Hardware > Tools > Light Bulb Changers
|
2570 |
+
Hardware > Tools > Lighters & Matches
|
2571 |
+
Hardware > Tools > Log Splitters
|
2572 |
+
Hardware > Tools > Magnetic Sweepers
|
2573 |
+
Hardware > Tools > Marking Tools
|
2574 |
+
Hardware > Tools > Masonry Tools
|
2575 |
+
Hardware > Tools > Masonry Tools > Brick Tools
|
2576 |
+
Hardware > Tools > Masonry Tools > Cement Mixers
|
2577 |
+
Hardware > Tools > Masonry Tools > Construction Lines
|
2578 |
+
Hardware > Tools > Masonry Tools > Floats
|
2579 |
+
Hardware > Tools > Masonry Tools > Grout Sponges
|
2580 |
+
Hardware > Tools > Masonry Tools > Masonry Edgers & Groovers
|
2581 |
+
Hardware > Tools > Masonry Tools > Masonry Jointers
|
2582 |
+
Hardware > Tools > Masonry Tools > Masonry Trowels
|
2583 |
+
Hardware > Tools > Masonry Tools > Power Trowels
|
2584 |
+
Hardware > Tools > Mattocks & Pickaxes
|
2585 |
+
Hardware > Tools > Measuring Tools & Sensors
|
2586 |
+
Hardware > Tools > Measuring Tools & Sensors > Air Quality Meters
|
2587 |
+
Hardware > Tools > Measuring Tools & Sensors > Altimeters
|
2588 |
+
Hardware > Tools > Measuring Tools & Sensors > Anemometers
|
2589 |
+
Hardware > Tools > Measuring Tools & Sensors > Barometers
|
2590 |
+
Hardware > Tools > Measuring Tools & Sensors > Calipers
|
2591 |
+
Hardware > Tools > Measuring Tools & Sensors > Cruising Rods
|
2592 |
+
Hardware > Tools > Measuring Tools & Sensors > Distance Meters
|
2593 |
+
Hardware > Tools > Measuring Tools & Sensors > Dividers
|
2594 |
+
Hardware > Tools > Measuring Tools & Sensors > Electrical Testing Tools
|
2595 |
+
Hardware > Tools > Measuring Tools & Sensors > Flow Meters & Controllers
|
2596 |
+
Hardware > Tools > Measuring Tools & Sensors > Gas Detectors
|
2597 |
+
Hardware > Tools > Measuring Tools & Sensors > Gauges
|
2598 |
+
Hardware > Tools > Measuring Tools & Sensors > Geiger Counters
|
2599 |
+
Hardware > Tools > Measuring Tools & Sensors > Hygrometers
|
2600 |
+
Hardware > Tools > Measuring Tools & Sensors > Infrared Thermometers
|
2601 |
+
Hardware > Tools > Measuring Tools & Sensors > Knife Guides
|
2602 |
+
Hardware > Tools > Measuring Tools & Sensors > Levels
|
2603 |
+
Hardware > Tools > Measuring Tools & Sensors > Levels > Bubble Levels
|
2604 |
+
Hardware > Tools > Measuring Tools & Sensors > Levels > Laser Levels
|
2605 |
+
Hardware > Tools > Measuring Tools & Sensors > Levels > Sight Levels
|
2606 |
+
Hardware > Tools > Measuring Tools & Sensors > Measuring Scales
|
2607 |
+
Hardware > Tools > Measuring Tools & Sensors > Measuring Wheels
|
2608 |
+
Hardware > Tools > Measuring Tools & Sensors > Moisture Meters
|
2609 |
+
Hardware > Tools > Measuring Tools & Sensors > Probes & Finders
|
2610 |
+
Hardware > Tools > Measuring Tools & Sensors > Protractors
|
2611 |
+
Hardware > Tools > Measuring Tools & Sensors > Rebar Locators
|
2612 |
+
Hardware > Tools > Measuring Tools & Sensors > Rulers
|
2613 |
+
Hardware > Tools > Measuring Tools & Sensors > Seismometer
|
2614 |
+
Hardware > Tools > Measuring Tools & Sensors > Sound Meters
|
2615 |
+
Hardware > Tools > Measuring Tools & Sensors > Squares
|
2616 |
+
Hardware > Tools > Measuring Tools & Sensors > Straight Edges
|
2617 |
+
Hardware > Tools > Measuring Tools & Sensors > Stud Sensors
|
2618 |
+
Hardware > Tools > Measuring Tools & Sensors > Tape Measures
|
2619 |
+
Hardware > Tools > Measuring Tools & Sensors > Theodolites
|
2620 |
+
Hardware > Tools > Measuring Tools & Sensors > Thermal Imaging Cameras
|
2621 |
+
Hardware > Tools > Measuring Tools & Sensors > Thermocouples & Thermopiles
|
2622 |
+
Hardware > Tools > Measuring Tools & Sensors > Transducers
|
2623 |
+
Hardware > Tools > Measuring Tools & Sensors > UV Light Meters
|
2624 |
+
Hardware > Tools > Measuring Tools & Sensors > Vibration Meters
|
2625 |
+
Hardware > Tools > Measuring Tools & Sensors > Weather Forecasters & Stations
|
2626 |
+
Hardware > Tools > Measuring Tools & Sensors > pH Meters
|
2627 |
+
Hardware > Tools > Milling Machines
|
2628 |
+
Hardware > Tools > Multifunction Power Tools
|
2629 |
+
Hardware > Tools > Nail Pullers
|
2630 |
+
Hardware > Tools > Nailers & Staplers
|
2631 |
+
Hardware > Tools > Oil Filter Drains
|
2632 |
+
Hardware > Tools > Paint Tools
|
2633 |
+
Hardware > Tools > Paint Tools > Airbrushes
|
2634 |
+
Hardware > Tools > Paint Tools > Paint Brushes
|
2635 |
+
Hardware > Tools > Paint Tools > Paint Edgers
|
2636 |
+
Hardware > Tools > Paint Tools > Paint Rollers
|
2637 |
+
Hardware > Tools > Paint Tools > Paint Shakers
|
2638 |
+
Hardware > Tools > Paint Tools > Paint Sponges
|
2639 |
+
Hardware > Tools > Paint Tools > Paint Sprayers
|
2640 |
+
Hardware > Tools > Paint Tools > Paint Strainers
|
2641 |
+
Hardware > Tools > Paint Tools > Paint Trays
|
2642 |
+
Hardware > Tools > Pickup Tools
|
2643 |
+
Hardware > Tools > Pipe & Bar Benders
|
2644 |
+
Hardware > Tools > Pipe & Tube Cleaners
|
2645 |
+
Hardware > Tools > Pipe Brushes
|
2646 |
+
Hardware > Tools > Planers
|
2647 |
+
Hardware > Tools > Planes
|
2648 |
+
Hardware > Tools > Pliers
|
2649 |
+
Hardware > Tools > Plungers
|
2650 |
+
Hardware > Tools > Polishers & Buffers
|
2651 |
+
Hardware > Tools > Post Hole Diggers
|
2652 |
+
Hardware > Tools > Pry Bars
|
2653 |
+
Hardware > Tools > Punches & Awls
|
2654 |
+
Hardware > Tools > Putty Knives & Scrapers
|
2655 |
+
Hardware > Tools > Reamers
|
2656 |
+
Hardware > Tools > Riveting Tools
|
2657 |
+
Hardware > Tools > Riveting Tools > Rivet Guns
|
2658 |
+
Hardware > Tools > Riveting Tools > Rivet Pliers
|
2659 |
+
Hardware > Tools > Routing Tools
|
2660 |
+
Hardware > Tools > Sanders
|
2661 |
+
Hardware > Tools > Sanding Blocks
|
2662 |
+
Hardware > Tools > Saw Horses
|
2663 |
+
Hardware > Tools > Saws
|
2664 |
+
Hardware > Tools > Saws > Band Saws
|
2665 |
+
Hardware > Tools > Saws > Cut-Off Saws
|
2666 |
+
Hardware > Tools > Saws > Hand Saws
|
2667 |
+
Hardware > Tools > Saws > Handheld Circular Saws
|
2668 |
+
Hardware > Tools > Saws > Jigsaws
|
2669 |
+
Hardware > Tools > Saws > Masonry & Tile Saws
|
2670 |
+
Hardware > Tools > Saws > Miter Saws
|
2671 |
+
Hardware > Tools > Saws > Panel Saws
|
2672 |
+
Hardware > Tools > Saws > Reciprocating Saws
|
2673 |
+
Hardware > Tools > Saws > Scroll Saws
|
2674 |
+
Hardware > Tools > Saws > Table Saws
|
2675 |
+
Hardware > Tools > Screwdrivers
|
2676 |
+
Hardware > Tools > Shapers
|
2677 |
+
Hardware > Tools > Sharpeners
|
2678 |
+
Hardware > Tools > Socket Drivers
|
2679 |
+
Hardware > Tools > Soldering Irons
|
2680 |
+
Hardware > Tools > Tap Reseaters
|
2681 |
+
Hardware > Tools > Taps & Dies
|
2682 |
+
Hardware > Tools > Threading Machines
|
2683 |
+
Hardware > Tools > Tool Clamps & Vises
|
2684 |
+
Hardware > Tools > Tool Files
|
2685 |
+
Hardware > Tools > Tool Keys
|
2686 |
+
Hardware > Tools > Tool Knives
|
2687 |
+
Hardware > Tools > Tool Sets
|
2688 |
+
Hardware > Tools > Tool Sets > Hand Tool Sets
|
2689 |
+
Hardware > Tools > Tool Sets > Power Tool Combo Sets
|
2690 |
+
Hardware > Tools > Welding Guns & Plasma Cutters
|
2691 |
+
Hardware > Tools > Wire & Cable Hand Tools
|
2692 |
+
Hardware > Tools > Work Lights
|
2693 |
+
Hardware > Tools > Wrenches
|
2694 |
+
Health & Beauty
|
2695 |
+
Health & Beauty > Health Care
|
2696 |
+
Health & Beauty > Health Care > Acupuncture
|
2697 |
+
Health & Beauty > Health Care > Acupuncture > Acupuncture Models
|
2698 |
+
Health & Beauty > Health Care > Acupuncture > Acupuncture Needles
|
2699 |
+
Health & Beauty > Health Care > Bed Pans
|
2700 |
+
Health & Beauty > Health Care > Biometric Monitor Accessories
|
2701 |
+
Health & Beauty > Health Care > Biometric Monitor Accessories > Activity Monitor Accessories
|
2702 |
+
Health & Beauty > Health Care > Biometric Monitor Accessories > Blood Glucose Meter Accessories
|
2703 |
+
Health & Beauty > Health Care > Biometric Monitor Accessories > Blood Glucose Meter Accessories > Blood Glucose Control Solution
|
2704 |
+
Health & Beauty > Health Care > Biometric Monitor Accessories > Blood Glucose Meter Accessories > Blood Glucose Test Strips
|
2705 |
+
Health & Beauty > Health Care > Biometric Monitor Accessories > Blood Glucose Meter Accessories > Lancing Devices
|
2706 |
+
Health & Beauty > Health Care > Biometric Monitor Accessories > Blood Pressure Monitor Accessories
|
2707 |
+
Health & Beauty > Health Care > Biometric Monitor Accessories > Blood Pressure Monitor Accessories > Blood Pressure Monitor Cuffs
|
2708 |
+
Health & Beauty > Health Care > Biometric Monitor Accessories > Body Weight Scale Accessories
|
2709 |
+
Health & Beauty > Health Care > Biometric Monitors
|
2710 |
+
Health & Beauty > Health Care > Biometric Monitors > Activity Monitors
|
2711 |
+
Health & Beauty > Health Care > Biometric Monitors > Blood Glucose Meters
|
2712 |
+
Health & Beauty > Health Care > Biometric Monitors > Blood Pressure Monitors
|
2713 |
+
Health & Beauty > Health Care > Biometric Monitors > Body Fat Analyzers
|
2714 |
+
Health & Beauty > Health Care > Biometric Monitors > Body Weight Scales
|
2715 |
+
Health & Beauty > Health Care > Biometric Monitors > Breathalyzers
|
2716 |
+
Health & Beauty > Health Care > Biometric Monitors > Cholesterol Analyzers
|
2717 |
+
Health & Beauty > Health Care > Biometric Monitors > Fertility Monitors and Ovulation Tests
|
2718 |
+
Health & Beauty > Health Care > Biometric Monitors > Fertility Monitors and Ovulation Tests > Fertility Tests & Monitors
|
2719 |
+
Health & Beauty > Health Care > Biometric Monitors > Fertility Monitors and Ovulation Tests > Ovulation Tests
|
2720 |
+
Health & Beauty > Health Care > Biometric Monitors > Medical Thermometers
|
2721 |
+
Health & Beauty > Health Care > Biometric Monitors > Prenatal Heart Rate Monitors
|
2722 |
+
Health & Beauty > Health Care > Biometric Monitors > Pulse Oximeters
|
2723 |
+
Health & Beauty > Health Care > Condoms
|
2724 |
+
Health & Beauty > Health Care > Conductivity Gels & Lotions
|
2725 |
+
Health & Beauty > Health Care > Contraceptive Cases
|
2726 |
+
Health & Beauty > Health Care > First Aid
|
2727 |
+
Health & Beauty > Health Care > First Aid > Antiseptics & Cleaning Supplies
|
2728 |
+
Health & Beauty > Health Care > First Aid > Cast & Bandage Protectors
|
2729 |
+
Health & Beauty > Health Care > First Aid > Eye Wash Supplies
|
2730 |
+
Health & Beauty > Health Care > First Aid > First Aid Kits
|
2731 |
+
Health & Beauty > Health Care > First Aid > Hot & Cold Therapies
|
2732 |
+
Health & Beauty > Health Care > First Aid > Hot & Cold Therapies > Heat Rubs
|
2733 |
+
Health & Beauty > Health Care > First Aid > Hot & Cold Therapies > Heating Pads
|
2734 |
+
Health & Beauty > Health Care > First Aid > Hot & Cold Therapies > Ice Packs
|
2735 |
+
Health & Beauty > Health Care > First Aid > Medical Tape & Bandages
|
2736 |
+
Health & Beauty > Health Care > Fitness & Nutrition
|
2737 |
+
Health & Beauty > Health Care > Fitness & Nutrition > Nutrition Bars
|
2738 |
+
Health & Beauty > Health Care > Fitness & Nutrition > Nutrition Drinks & Shakes
|
2739 |
+
Health & Beauty > Health Care > Fitness & Nutrition > Nutrition Gels & Chews
|
2740 |
+
Health & Beauty > Health Care > Fitness & Nutrition > Nutritional Food Purées
|
2741 |
+
Health & Beauty > Health Care > Fitness & Nutrition > Tube Feeding Supplements
|
2742 |
+
Health & Beauty > Health Care > Fitness & Nutrition > Vitamins & Supplements
|
2743 |
+
Health & Beauty > Health Care > Hearing Aids
|
2744 |
+
Health & Beauty > Health Care > Incontinence Aids
|
2745 |
+
Health & Beauty > Health Care > Light Therapy Lamps
|
2746 |
+
Health & Beauty > Health Care > Medical Alarm Systems
|
2747 |
+
Health & Beauty > Health Care > Medical Identification Tags & Jewelry
|
2748 |
+
Health & Beauty > Health Care > Medical Tests
|
2749 |
+
Health & Beauty > Health Care > Medical Tests > Allergy Test Kits
|
2750 |
+
Health & Beauty > Health Care > Medical Tests > Blood Typing Test Kits
|
2751 |
+
Health & Beauty > Health Care > Medical Tests > Drug Tests
|
2752 |
+
Health & Beauty > Health Care > Medical Tests > HIV Tests
|
2753 |
+
Health & Beauty > Health Care > Medical Tests > Pregnancy Tests
|
2754 |
+
Health & Beauty > Health Care > Medical Tests > Urinary Tract Infection Tests
|
2755 |
+
Health & Beauty > Health Care > Medicine & Drugs
|
2756 |
+
Health & Beauty > Health Care > Mobility & Accessibility
|
2757 |
+
Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Equipment
|
2758 |
+
Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Equipment > Mobility Scooters
|
2759 |
+
Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Equipment > Stair Lifts
|
2760 |
+
Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Equipment > Transfer Boards & Sheets
|
2761 |
+
Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Equipment > Wheelchairs
|
2762 |
+
Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Equipment Accessories
|
2763 |
+
Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Furniture & Fixtures
|
2764 |
+
Health & Beauty > Health Care > Mobility & Accessibility > Accessibility Furniture & Fixtures > Shower Benches & Seats
|
2765 |
+
Health & Beauty > Health Care > Mobility & Accessibility > Walking Aid Accessories
|
2766 |
+
Health & Beauty > Health Care > Mobility & Accessibility > Walking Aids
|
2767 |
+
Health & Beauty > Health Care > Mobility & Accessibility > Walking Aids > Canes & Walking Sticks
|
2768 |
+
Health & Beauty > Health Care > Mobility & Accessibility > Walking Aids > Crutches
|
2769 |
+
Health & Beauty > Health Care > Mobility & Accessibility > Walking Aids > Walkers
|
2770 |
+
Health & Beauty > Health Care > Occupational & Physical Therapy Equipment
|
2771 |
+
Health & Beauty > Health Care > Occupational & Physical Therapy Equipment > Electrical Muscle Stimulators
|
2772 |
+
Health & Beauty > Health Care > Occupational & Physical Therapy Equipment > Therapeutic Swings
|
2773 |
+
Health & Beauty > Health Care > Pillboxes
|
2774 |
+
Health & Beauty > Health Care > Respiratory Care
|
2775 |
+
Health & Beauty > Health Care > Respiratory Care > Nebulizers
|
2776 |
+
Health & Beauty > Health Care > Respiratory Care > Oxygen Tanks
|
2777 |
+
Health & Beauty > Health Care > Respiratory Care > PAP Machines
|
2778 |
+
Health & Beauty > Health Care > Respiratory Care > PAP Masks
|
2779 |
+
Health & Beauty > Health Care > Respiratory Care > Steam Inhalers
|
2780 |
+
Health & Beauty > Health Care > Specimen Cups
|
2781 |
+
Health & Beauty > Health Care > Spermicides
|
2782 |
+
Health & Beauty > Health Care > Stump Shrinkers
|
2783 |
+
Health & Beauty > Health Care > Supports & Braces
|
2784 |
+
Health & Beauty > Health Care > Surgical Lubricants
|
2785 |
+
Health & Beauty > Jewelry Cleaning & Care
|
2786 |
+
Health & Beauty > Jewelry Cleaning & Care > Jewelry Cleaning Solutions & Polishes
|
2787 |
+
Health & Beauty > Jewelry Cleaning & Care > Jewelry Cleaning Tools
|
2788 |
+
Health & Beauty > Jewelry Cleaning & Care > Jewelry Holders
|
2789 |
+
Health & Beauty > Jewelry Cleaning & Care > Jewelry Steam Cleaners
|
2790 |
+
Health & Beauty > Jewelry Cleaning & Care > Watch Repair Kits
|
2791 |
+
Health & Beauty > Personal Care
|
2792 |
+
Health & Beauty > Personal Care > Back Care
|
2793 |
+
Health & Beauty > Personal Care > Back Care > Back & Lumbar Support Cushions
|
2794 |
+
Health & Beauty > Personal Care > Cosmetics
|
2795 |
+
Health & Beauty > Personal Care > Cosmetics > Bath & Body
|
2796 |
+
Health & Beauty > Personal Care > Cosmetics > Bath & Body > Adult Hygienic Wipes
|
2797 |
+
Health & Beauty > Personal Care > Cosmetics > Bath & Body > Bar Soap
|
2798 |
+
Health & Beauty > Personal Care > Cosmetics > Bath & Body > Bath Additives
|
2799 |
+
Health & Beauty > Personal Care > Cosmetics > Bath & Body > Bath Brushes
|
2800 |
+
Health & Beauty > Personal Care > Cosmetics > Bath & Body > Bath Sponges & Loofahs
|
2801 |
+
Health & Beauty > Personal Care > Cosmetics > Bath & Body > Body Wash
|
2802 |
+
Health & Beauty > Personal Care > Cosmetics > Bath & Body > Hand Sanitizers & Wipes
|
2803 |
+
Health & Beauty > Personal Care > Cosmetics > Bath & Body > Liquid Hand Soap
|
2804 |
+
Health & Beauty > Personal Care > Cosmetics > Bath & Body > Powdered Hand Soap
|
2805 |
+
Health & Beauty > Personal Care > Cosmetics > Bath & Body > Shower Caps
|
2806 |
+
Health & Beauty > Personal Care > Cosmetics > Bath & Body Gift Sets
|
2807 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Sets
|
2808 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tool Cleansers
|
2809 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools
|
2810 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools
|
2811 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Double Eyelid Glue & Tape
|
2812 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Eyebrow Stencils
|
2813 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Eyelash Curler Refills
|
2814 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Eyelash Curlers
|
2815 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Face Mirrors
|
2816 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Facial Blotting Paper
|
2817 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > False Eyelash Accessories
|
2818 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > False Eyelash Accessories > False Eyelash Adhesive
|
2819 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > False Eyelash Accessories > False Eyelash Applicators
|
2820 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > False Eyelash Accessories > False Eyelash Remover
|
2821 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Makeup Brushes
|
2822 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Makeup Sponges
|
2823 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Makeup Tools > Refillable Makeup Palettes & Cases
|
2824 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools
|
2825 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Cuticle Pushers
|
2826 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Cuticle Scissors
|
2827 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Manicure & Pedicure Spacers
|
2828 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Manicure Tool Sets
|
2829 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Nail Buffers
|
2830 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Nail Clippers
|
2831 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Nail Drill Accessories
|
2832 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Nail Drills
|
2833 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Nail Dryers
|
2834 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Nail Tools > Nail Files & Emery Boards
|
2835 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools
|
2836 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Facial Saunas
|
2837 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Foot Files
|
2838 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Lotion & Sunscreen Applicators
|
2839 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Pumice Stones
|
2840 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Skin Care Extractors
|
2841 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Skin Care Rollers
|
2842 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Skin Cleansing Brush Heads
|
2843 |
+
Health & Beauty > Personal Care > Cosmetics > Cosmetic Tools > Skin Care Tools > Skin Cleansing Brushes & Systems
|
2844 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup
|
2845 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Body Makeup
|
2846 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Body Makeup > Body & Hair Glitter
|
2847 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Body Makeup > Body Paint & Foundation
|
2848 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Costume & Stage Makeup
|
2849 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup
|
2850 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Eye Primer
|
2851 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Eye Shadow
|
2852 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Eyebrow Enhancers
|
2853 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Eyeliner
|
2854 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > False Eyelashes
|
2855 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Lash & Brow Growth Treatments
|
2856 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Mascara
|
2857 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Eye Makeup > Mascara Primer
|
2858 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Face Makeup
|
2859 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Face Makeup > Blushes & Bronzers
|
2860 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Face Makeup > Face Powder
|
2861 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Face Makeup > Face Primer
|
2862 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Face Makeup > Foundations & Concealers
|
2863 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Face Makeup > Highlighters & Luminizers
|
2864 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Lip Makeup
|
2865 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Lip Makeup > Lip & Cheek Stains
|
2866 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Lip Makeup > Lip Gloss
|
2867 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Lip Makeup > Lip Liner
|
2868 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Lip Makeup > Lip Primer
|
2869 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Lip Makeup > Lipstick
|
2870 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Makeup Finishing Sprays
|
2871 |
+
Health & Beauty > Personal Care > Cosmetics > Makeup > Temporary Tattoos
|
2872 |
+
Health & Beauty > Personal Care > Cosmetics > Nail Care
|
2873 |
+
Health & Beauty > Personal Care > Cosmetics > Nail Care > Cuticle Cream & Oil
|
2874 |
+
Health & Beauty > Personal Care > Cosmetics > Nail Care > False Nails
|
2875 |
+
Health & Beauty > Personal Care > Cosmetics > Nail Care > Manicure Glue
|
2876 |
+
Health & Beauty > Personal Care > Cosmetics > Nail Care > Nail Art Kits & Accessories
|
2877 |
+
Health & Beauty > Personal Care > Cosmetics > Nail Care > Nail Polish Drying Drops & Sprays
|
2878 |
+
Health & Beauty > Personal Care > Cosmetics > Nail Care > Nail Polish Removers
|
2879 |
+
Health & Beauty > Personal Care > Cosmetics > Nail Care > Nail Polish Thinners
|
2880 |
+
Health & Beauty > Personal Care > Cosmetics > Nail Care > Nail Polishes
|
2881 |
+
Health & Beauty > Personal Care > Cosmetics > Perfume & Cologne
|
2882 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care
|
2883 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Acne Treatments & Kits
|
2884 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Anti-Aging Skin Care Kits
|
2885 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Body Oil
|
2886 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Body Powder
|
2887 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Compressed Skin Care Mask Sheets
|
2888 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Facial Cleansers
|
2889 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Facial Cleansing Kits
|
2890 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Facial Pore Strips
|
2891 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Lip Balms & Treatments
|
2892 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Lip Balms & Treatments > Lip Balms
|
2893 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Lip Balms & Treatments > Medicated Lip Treatments
|
2894 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Lotion & Moisturizer
|
2895 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Makeup Removers
|
2896 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Petroleum Jelly
|
2897 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Skin Care Masks & Peels
|
2898 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Skin Insect Repellent
|
2899 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Sunscreen
|
2900 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Tanning Products
|
2901 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Tanning Products > Self Tanner
|
2902 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Tanning Products > Tanning Oil & Lotion
|
2903 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Toners & Astringents
|
2904 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Toners & Astringents > Astringents
|
2905 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Toners & Astringents > Toners
|
2906 |
+
Health & Beauty > Personal Care > Cosmetics > Skin Care > Wart Removers
|
2907 |
+
Health & Beauty > Personal Care > Cotton Balls
|
2908 |
+
Health & Beauty > Personal Care > Cotton Swabs
|
2909 |
+
Health & Beauty > Personal Care > Deodorant & Anti-Perspirant
|
2910 |
+
Health & Beauty > Personal Care > Deodorant & Anti-Perspirant > Anti-Perspirant
|
2911 |
+
Health & Beauty > Personal Care > Deodorant & Anti-Perspirant > Deodorant
|
2912 |
+
Health & Beauty > Personal Care > Ear Care
|
2913 |
+
Health & Beauty > Personal Care > Ear Care > Ear Candles
|
2914 |
+
Health & Beauty > Personal Care > Ear Care > Ear Drops
|
2915 |
+
Health & Beauty > Personal Care > Ear Care > Ear Dryers
|
2916 |
+
Health & Beauty > Personal Care > Ear Care > Ear Picks & Spoons
|
2917 |
+
Health & Beauty > Personal Care > Ear Care > Ear Syringes
|
2918 |
+
Health & Beauty > Personal Care > Ear Care > Ear Wax Removal Kits
|
2919 |
+
Health & Beauty > Personal Care > Ear Care > Earplug Dispensers
|
2920 |
+
Health & Beauty > Personal Care > Ear Care > Earplugs
|
2921 |
+
Health & Beauty > Personal Care > Enema Kits & Supplies
|
2922 |
+
Health & Beauty > Personal Care > Feminine Sanitary Supplies
|
2923 |
+
Health & Beauty > Personal Care > Feminine Sanitary Supplies > Feminine Deodorant
|
2924 |
+
Health & Beauty > Personal Care > Feminine Sanitary Supplies > Feminine Douches & Creams
|
2925 |
+
Health & Beauty > Personal Care > Feminine Sanitary Supplies > Feminine Pads & Protectors
|
2926 |
+
Health & Beauty > Personal Care > Feminine Sanitary Supplies > Menstrual Cups
|
2927 |
+
Health & Beauty > Personal Care > Feminine Sanitary Supplies > Tampons
|
2928 |
+
Health & Beauty > Personal Care > Foot Care
|
2929 |
+
Health & Beauty > Personal Care > Foot Care > Bunion Care Supplies
|
2930 |
+
Health & Beauty > Personal Care > Foot Care > Corn & Callus Care Supplies
|
2931 |
+
Health & Beauty > Personal Care > Foot Care > Foot Odor Removers
|
2932 |
+
Health & Beauty > Personal Care > Foot Care > Insoles & Inserts
|
2933 |
+
Health & Beauty > Personal Care > Foot Care > Toe Spacers
|
2934 |
+
Health & Beauty > Personal Care > Hair Care
|
2935 |
+
Health & Beauty > Personal Care > Hair Care > Hair Care Kits
|
2936 |
+
Health & Beauty > Personal Care > Hair Care > Hair Color
|
2937 |
+
Health & Beauty > Personal Care > Hair Care > Hair Color Removers
|
2938 |
+
Health & Beauty > Personal Care > Hair Care > Hair Coloring Accessories
|
2939 |
+
Health & Beauty > Personal Care > Hair Care > Hair Loss Concealers
|
2940 |
+
Health & Beauty > Personal Care > Hair Care > Hair Loss Treatments
|
2941 |
+
Health & Beauty > Personal Care > Hair Care > Hair Permanents & Straighteners
|
2942 |
+
Health & Beauty > Personal Care > Hair Care > Hair Shears
|
2943 |
+
Health & Beauty > Personal Care > Hair Care > Hair Steamers & Heat Caps
|
2944 |
+
Health & Beauty > Personal Care > Hair Care > Hair Styling Products
|
2945 |
+
Health & Beauty > Personal Care > Hair Care > Hair Styling Tool Accessories
|
2946 |
+
Health & Beauty > Personal Care > Hair Care > Hair Styling Tool Accessories > Hair Curler Clips & Pins
|
2947 |
+
Health & Beauty > Personal Care > Hair Care > Hair Styling Tool Accessories > Hair Dryer Accessories
|
2948 |
+
Health & Beauty > Personal Care > Hair Care > Hair Styling Tool Accessories > Hair Iron Accessories
|
2949 |
+
Health & Beauty > Personal Care > Hair Care > Hair Styling Tools
|
2950 |
+
Health & Beauty > Personal Care > Hair Care > Hair Styling Tools > Combs & Brushes
|
2951 |
+
Health & Beauty > Personal Care > Hair Care > Hair Styling Tools > Curling Irons
|
2952 |
+
Health & Beauty > Personal Care > Hair Care > Hair Styling Tools > Hair Curlers
|
2953 |
+
Health & Beauty > Personal Care > Hair Care > Hair Styling Tools > Hair Dryers
|
2954 |
+
Health & Beauty > Personal Care > Hair Care > Hair Styling Tools > Hair Straighteners
|
2955 |
+
Health & Beauty > Personal Care > Hair Care > Hair Styling Tools > Hair Styling Tool Sets
|
2956 |
+
Health & Beauty > Personal Care > Hair Care > Shampoo & Conditioner
|
2957 |
+
Health & Beauty > Personal Care > Hair Care > Shampoo & Conditioner > Conditioners
|
2958 |
+
Health & Beauty > Personal Care > Hair Care > Shampoo & Conditioner > Shampoo
|
2959 |
+
Health & Beauty > Personal Care > Hair Care > Shampoo & Conditioner > Shampoo & Conditioner Sets
|
2960 |
+
Health & Beauty > Personal Care > Massage & Relaxation
|
2961 |
+
Health & Beauty > Personal Care > Massage & Relaxation > Back Scratchers
|
2962 |
+
Health & Beauty > Personal Care > Massage & Relaxation > Eye Pillows
|
2963 |
+
Health & Beauty > Personal Care > Massage & Relaxation > Massage Chairs
|
2964 |
+
Health & Beauty > Personal Care > Massage & Relaxation > Massage Oil
|
2965 |
+
Health & Beauty > Personal Care > Massage & Relaxation > Massage Stone Warmers
|
2966 |
+
Health & Beauty > Personal Care > Massage & Relaxation > Massage Stones
|
2967 |
+
Health & Beauty > Personal Care > Massage & Relaxation > Massage Tables
|
2968 |
+
Health & Beauty > Personal Care > Massage & Relaxation > Massagers
|
2969 |
+
Health & Beauty > Personal Care > Massage & Relaxation > Massagers > Electric Massagers
|
2970 |
+
Health & Beauty > Personal Care > Massage & Relaxation > Massagers > Manual Massage Tools
|
2971 |
+
Health & Beauty > Personal Care > Massage & Relaxation > Massagers > Massage Cushions
|
2972 |
+
Health & Beauty > Personal Care > Oral Care
|
2973 |
+
Health & Beauty > Personal Care > Oral Care > Breath Spray
|
2974 |
+
Health & Beauty > Personal Care > Oral Care > Dental Floss
|
2975 |
+
Health & Beauty > Personal Care > Oral Care > Dental Mouthguards
|
2976 |
+
Health & Beauty > Personal Care > Oral Care > Dental Water Jet Replacement Tips
|
2977 |
+
Health & Beauty > Personal Care > Oral Care > Dental Water Jets
|
2978 |
+
Health & Beauty > Personal Care > Oral Care > Denture Adhesives
|
2979 |
+
Health & Beauty > Personal Care > Oral Care > Denture Cleaners
|
2980 |
+
Health & Beauty > Personal Care > Oral Care > Denture Repair Kits
|
2981 |
+
Health & Beauty > Personal Care > Oral Care > Dentures
|
2982 |
+
Health & Beauty > Personal Care > Oral Care > Gum Stimulators
|
2983 |
+
Health & Beauty > Personal Care > Oral Care > Mouthwash
|
2984 |
+
Health & Beauty > Personal Care > Oral Care > Orthodontic Appliance Cases
|
2985 |
+
Health & Beauty > Personal Care > Oral Care > Power Flossers
|
2986 |
+
Health & Beauty > Personal Care > Oral Care > Teeth Whiteners
|
2987 |
+
Health & Beauty > Personal Care > Oral Care > Tongue Scrapers
|
2988 |
+
Health & Beauty > Personal Care > Oral Care > Toothbrush Accessories
|
2989 |
+
Health & Beauty > Personal Care > Oral Care > Toothbrush Accessories > Toothbrush Covers
|
2990 |
+
Health & Beauty > Personal Care > Oral Care > Toothbrush Accessories > Toothbrush Replacement Heads
|
2991 |
+
Health & Beauty > Personal Care > Oral Care > Toothbrush Accessories > Toothbrush Sanitizers
|
2992 |
+
Health & Beauty > Personal Care > Oral Care > Toothbrushes
|
2993 |
+
Health & Beauty > Personal Care > Oral Care > Toothpaste
|
2994 |
+
Health & Beauty > Personal Care > Oral Care > Toothpaste Squeezers & Dispensers
|
2995 |
+
Health & Beauty > Personal Care > Oral Care > Toothpicks
|
2996 |
+
Health & Beauty > Personal Care > Personal Lubricants
|
2997 |
+
Health & Beauty > Personal Care > Shaving & Grooming
|
2998 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Aftershave
|
2999 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Body & Facial Hair Bleach
|
3000 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Electric Razor Accessories
|
3001 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Electric Razors
|
3002 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Hair Clipper & Trimmer Accessories
|
3003 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Hair Clippers & Trimmers
|
3004 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal
|
3005 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal > Depilatories
|
3006 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal > Electrolysis Devices
|
3007 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal > Epilators
|
3008 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal > Hair Removal Wax Warmers
|
3009 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal > Laser & IPL Hair Removal Devices
|
3010 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Hair Removal > Waxing Kits & Supplies
|
3011 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Razors & Razor Blades
|
3012 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Shaving Bowls & Mugs
|
3013 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Shaving Brushes
|
3014 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Shaving Cream
|
3015 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Shaving Kits
|
3016 |
+
Health & Beauty > Personal Care > Shaving & Grooming > Styptic Pencils
|
3017 |
+
Health & Beauty > Personal Care > Sleeping Aids
|
3018 |
+
Health & Beauty > Personal Care > Sleeping Aids > Eye Masks
|
3019 |
+
Health & Beauty > Personal Care > Sleeping Aids > Snoring & Sleep Apnea Aids
|
3020 |
+
Health & Beauty > Personal Care > Sleeping Aids > Travel Pillows
|
3021 |
+
Health & Beauty > Personal Care > Sleeping Aids > White Noise Machines
|
3022 |
+
Health & Beauty > Personal Care > Spray Tanning Tents
|
3023 |
+
Health & Beauty > Personal Care > Tanning Beds
|
3024 |
+
Health & Beauty > Personal Care > Tweezers
|
3025 |
+
Health & Beauty > Personal Care > Vision Care
|
3026 |
+
Health & Beauty > Personal Care > Vision Care > Contact Lens Care
|
3027 |
+
Health & Beauty > Personal Care > Vision Care > Contact Lens Care > Contact Lens Care Kits
|
3028 |
+
Health & Beauty > Personal Care > Vision Care > Contact Lens Care > Contact Lens Cases
|
3029 |
+
Health & Beauty > Personal Care > Vision Care > Contact Lens Care > Contact Lens Solution
|
3030 |
+
Health & Beauty > Personal Care > Vision Care > Contact Lenses
|
3031 |
+
Health & Beauty > Personal Care > Vision Care > Eye Drops & Lubricants
|
3032 |
+
Health & Beauty > Personal Care > Vision Care > Eyeglass Lenses
|
3033 |
+
Health & Beauty > Personal Care > Vision Care > Eyeglasses
|
3034 |
+
Health & Beauty > Personal Care > Vision Care > Eyewear Accessories
|
3035 |
+
Health & Beauty > Personal Care > Vision Care > Eyewear Accessories > Eyewear Cases & Holders
|
3036 |
+
Health & Beauty > Personal Care > Vision Care > Eyewear Accessories > Eyewear Lens Cleaning Solutions
|
3037 |
+
Health & Beauty > Personal Care > Vision Care > Eyewear Accessories > Eyewear Replacement Parts
|
3038 |
+
Health & Beauty > Personal Care > Vision Care > Eyewear Accessories > Eyewear Straps & Chains
|
3039 |
+
Health & Beauty > Personal Care > Vision Care > Sunglass Lenses
|
3040 |
+
Home & Garden
|
3041 |
+
Home & Garden > Bathroom Accessories
|
3042 |
+
Home & Garden > Bathroom Accessories > Bath Caddies
|
3043 |
+
Home & Garden > Bathroom Accessories > Bath Mats & Rugs
|
3044 |
+
Home & Garden > Bathroom Accessories > Bath Pillows
|
3045 |
+
Home & Garden > Bathroom Accessories > Bathroom Accessory Mounts
|
3046 |
+
Home & Garden > Bathroom Accessories > Bathroom Accessory Sets
|
3047 |
+
Home & Garden > Bathroom Accessories > Facial Tissue Holders
|
3048 |
+
Home & Garden > Bathroom Accessories > Hand Dryer Accessories
|
3049 |
+
Home & Garden > Bathroom Accessories > Hand Dryers
|
3050 |
+
Home & Garden > Bathroom Accessories > Medicine Cabinets
|
3051 |
+
Home & Garden > Bathroom Accessories > Robe Hooks
|
3052 |
+
Home & Garden > Bathroom Accessories > Safety Grab Bars
|
3053 |
+
Home & Garden > Bathroom Accessories > Shower Curtain Rings
|
3054 |
+
Home & Garden > Bathroom Accessories > Shower Curtains
|
3055 |
+
Home & Garden > Bathroom Accessories > Shower Rods
|
3056 |
+
Home & Garden > Bathroom Accessories > Soap & Lotion Dispensers
|
3057 |
+
Home & Garden > Bathroom Accessories > Soap Dishes & Holders
|
3058 |
+
Home & Garden > Bathroom Accessories > Toilet Brush Replacement Heads
|
3059 |
+
Home & Garden > Bathroom Accessories > Toilet Brushes & Holders
|
3060 |
+
Home & Garden > Bathroom Accessories > Toilet Paper Holders
|
3061 |
+
Home & Garden > Bathroom Accessories > Toothbrush Holders
|
3062 |
+
Home & Garden > Bathroom Accessories > Towel Racks & Holders
|
3063 |
+
Home & Garden > Business & Home Security
|
3064 |
+
Home & Garden > Business & Home Security > Dummy Surveillance Cameras
|
3065 |
+
Home & Garden > Business & Home Security > Home Alarm Systems
|
3066 |
+
Home & Garden > Business & Home Security > Motion Sensors
|
3067 |
+
Home & Garden > Business & Home Security > Safety & Security Mirrors
|
3068 |
+
Home & Garden > Business & Home Security > Security Lights
|
3069 |
+
Home & Garden > Business & Home Security > Security Monitors & Recorders
|
3070 |
+
Home & Garden > Business & Home Security > Security Safe Accessories
|
3071 |
+
Home & Garden > Business & Home Security > Security Safes
|
3072 |
+
Home & Garden > Business & Home Security > Security System Sensors
|
3073 |
+
Home & Garden > Decor
|
3074 |
+
Home & Garden > Decor > Address Signs
|
3075 |
+
Home & Garden > Decor > Artificial Flora
|
3076 |
+
Home & Garden > Decor > Artificial Food
|
3077 |
+
Home & Garden > Decor > Artwork
|
3078 |
+
Home & Garden > Decor > Artwork > Decorative Tapestries
|
3079 |
+
Home & Garden > Decor > Artwork > Posters, Prints, & Visual Artwork
|
3080 |
+
Home & Garden > Decor > Artwork > Sculptures & Statues
|
3081 |
+
Home & Garden > Decor > Backrest Pillows
|
3082 |
+
Home & Garden > Decor > Baskets
|
3083 |
+
Home & Garden > Decor > Bird & Wildlife Feeder Accessories
|
3084 |
+
Home & Garden > Decor > Bird & Wildlife Feeders
|
3085 |
+
Home & Garden > Decor > Bird & Wildlife Feeders > Bird Feeders
|
3086 |
+
Home & Garden > Decor > Bird & Wildlife Feeders > Butterfly Feeders
|
3087 |
+
Home & Garden > Decor > Bird & Wildlife Feeders > Squirrel Feeders
|
3088 |
+
Home & Garden > Decor > Bird & Wildlife House Accessories
|
3089 |
+
Home & Garden > Decor > Bird & Wildlife Houses
|
3090 |
+
Home & Garden > Decor > Bird & Wildlife Houses > Bat Houses
|
3091 |
+
Home & Garden > Decor > Bird & Wildlife Houses > Birdhouses
|
3092 |
+
Home & Garden > Decor > Bird & Wildlife Houses > Butterfly Houses
|
3093 |
+
Home & Garden > Decor > Bird Baths
|
3094 |
+
Home & Garden > Decor > Bookends
|
3095 |
+
Home & Garden > Decor > Cardboard Cutouts
|
3096 |
+
Home & Garden > Decor > Chair & Sofa Cushions
|
3097 |
+
Home & Garden > Decor > Clock Parts
|
3098 |
+
Home & Garden > Decor > Clocks
|
3099 |
+
Home & Garden > Decor > Clocks > Alarm Clocks
|
3100 |
+
Home & Garden > Decor > Clocks > Desk & Shelf Clocks
|
3101 |
+
Home & Garden > Decor > Clocks > Floor & Grandfather Clocks
|
3102 |
+
Home & Garden > Decor > Clocks > Wall Clocks
|
3103 |
+
Home & Garden > Decor > Coat & Hat Racks
|
3104 |
+
Home & Garden > Decor > Decorative Bells
|
3105 |
+
Home & Garden > Decor > Decorative Bottles
|
3106 |
+
Home & Garden > Decor > Decorative Bowls
|
3107 |
+
Home & Garden > Decor > Decorative Jars
|
3108 |
+
Home & Garden > Decor > Decorative Plaques
|
3109 |
+
Home & Garden > Decor > Decorative Plates
|
3110 |
+
Home & Garden > Decor > Decorative Trays
|
3111 |
+
Home & Garden > Decor > Door Mats
|
3112 |
+
Home & Garden > Decor > Dreamcatchers
|
3113 |
+
Home & Garden > Decor > Dried Flowers
|
3114 |
+
Home & Garden > Decor > Ecospheres
|
3115 |
+
Home & Garden > Decor > Figurines
|
3116 |
+
Home & Garden > Decor > Finials
|
3117 |
+
Home & Garden > Decor > Flag & Windsock Accessories
|
3118 |
+
Home & Garden > Decor > Flag & Windsock Accessories > Flag & Windsock Pole Lights
|
3119 |
+
Home & Garden > Decor > Flag & Windsock Accessories > Flag & Windsock Pole Mounting Hardware & Kits
|
3120 |
+
Home & Garden > Decor > Flag & Windsock Accessories > Flag & Windsock Poles
|
3121 |
+
Home & Garden > Decor > Flags & Windsocks
|
3122 |
+
Home & Garden > Decor > Flameless Candles
|
3123 |
+
Home & Garden > Decor > Fountains & Ponds
|
3124 |
+
Home & Garden > Decor > Fountains & Ponds > Fountain & Pond Accessories
|
3125 |
+
Home & Garden > Decor > Fountains & Ponds > Fountains & Waterfalls
|
3126 |
+
Home & Garden > Decor > Fountains & Ponds > Ponds
|
3127 |
+
Home & Garden > Decor > Garden & Stepping Stones
|
3128 |
+
Home & Garden > Decor > Growth Charts
|
3129 |
+
Home & Garden > Decor > Home Decor Decals
|
3130 |
+
Home & Garden > Decor > Home Fragrance Accessories
|
3131 |
+
Home & Garden > Decor > Home Fragrance Accessories > Candle & Oil Warmers
|
3132 |
+
Home & Garden > Decor > Home Fragrance Accessories > Candle Holders
|
3133 |
+
Home & Garden > Decor > Home Fragrance Accessories > Candle Snuffers
|
3134 |
+
Home & Garden > Decor > Home Fragrance Accessories > Incense Holders
|
3135 |
+
Home & Garden > Decor > Home Fragrances
|
3136 |
+
Home & Garden > Decor > Home Fragrances > Air Fresheners
|
3137 |
+
Home & Garden > Decor > Home Fragrances > Candles
|
3138 |
+
Home & Garden > Decor > Home Fragrances > Fragrance Oil
|
3139 |
+
Home & Garden > Decor > Home Fragrances > Incense
|
3140 |
+
Home & Garden > Decor > Home Fragrances > Potpourri
|
3141 |
+
Home & Garden > Decor > Home Fragrances > Wax Tarts
|
3142 |
+
Home & Garden > Decor > Hourglasses
|
3143 |
+
Home & Garden > Decor > House Numbers & Letters
|
3144 |
+
Home & Garden > Decor > Lawn Ornaments & Garden Sculptures
|
3145 |
+
Home & Garden > Decor > Mail Slots
|
3146 |
+
Home & Garden > Decor > Mailbox Accessories
|
3147 |
+
Home & Garden > Decor > Mailbox Accessories > Mailbox Covers
|
3148 |
+
Home & Garden > Decor > Mailbox Accessories > Mailbox Enclosures
|
3149 |
+
Home & Garden > Decor > Mailbox Accessories > Mailbox Flags
|
3150 |
+
Home & Garden > Decor > Mailbox Accessories > Mailbox Posts
|
3151 |
+
Home & Garden > Decor > Mailbox Accessories > Mailbox Replacement Doors
|
3152 |
+
Home & Garden > Decor > Mailboxes
|
3153 |
+
Home & Garden > Decor > Mirrors
|
3154 |
+
Home & Garden > Decor > Music Boxes
|
3155 |
+
Home & Garden > Decor > Napkin Rings
|
3156 |
+
Home & Garden > Decor > Novelty Signs
|
3157 |
+
Home & Garden > Decor > Ottoman Cushions
|
3158 |
+
Home & Garden > Decor > Picture Frames
|
3159 |
+
Home & Garden > Decor > Piggy Banks & Money Jars
|
3160 |
+
Home & Garden > Decor > Rain Chains
|
3161 |
+
Home & Garden > Decor > Rain Gauges
|
3162 |
+
Home & Garden > Decor > Refrigerator Magnets
|
3163 |
+
Home & Garden > Decor > Rugs
|
3164 |
+
Home & Garden > Decor > Seasonal & Holiday Decorations
|
3165 |
+
Home & Garden > Decor > Seasonal & Holiday Decorations > Advent Calendars
|
3166 |
+
Home & Garden > Decor > Seasonal & Holiday Decorations > Christmas Tree Skirts
|
3167 |
+
Home & Garden > Decor > Seasonal & Holiday Decorations > Christmas Tree Stands
|
3168 |
+
Home & Garden > Decor > Seasonal & Holiday Decorations > Easter Egg Decorating Kits
|
3169 |
+
Home & Garden > Decor > Seasonal & Holiday Decorations > Holiday Ornament Displays & Stands
|
3170 |
+
Home & Garden > Decor > Seasonal & Holiday Decorations > Holiday Ornament Hooks
|
3171 |
+
Home & Garden > Decor > Seasonal & Holiday Decorations > Holiday Ornaments
|
3172 |
+
Home & Garden > Decor > Seasonal & Holiday Decorations > Holiday Stocking Hangers
|
3173 |
+
Home & Garden > Decor > Seasonal & Holiday Decorations > Holiday Stockings
|
3174 |
+
Home & Garden > Decor > Seasonal & Holiday Decorations > Japanese Traditional Dolls
|
3175 |
+
Home & Garden > Decor > Seasonal & Holiday Decorations > Nativity Sets
|
3176 |
+
Home & Garden > Decor > Seasonal & Holiday Decorations > Seasonal Village Sets & Accessories
|
3177 |
+
Home & Garden > Decor > Shadow Boxes
|
3178 |
+
Home & Garden > Decor > Slipcovers
|
3179 |
+
Home & Garden > Decor > Snow Globes
|
3180 |
+
Home & Garden > Decor > Suncatchers
|
3181 |
+
Home & Garden > Decor > Sundials
|
3182 |
+
Home & Garden > Decor > Throw Pillows
|
3183 |
+
Home & Garden > Decor > Trunks
|
3184 |
+
Home & Garden > Decor > Vase Fillers & Table Scatters
|
3185 |
+
Home & Garden > Decor > Vases
|
3186 |
+
Home & Garden > Decor > Wallpaper
|
3187 |
+
Home & Garden > Decor > Weather Vanes & Roof Decor
|
3188 |
+
Home & Garden > Decor > Wind Chimes
|
3189 |
+
Home & Garden > Decor > Wind Wheels & Spinners
|
3190 |
+
Home & Garden > Decor > Window Magnets
|
3191 |
+
Home & Garden > Decor > Window Treatment Accessories
|
3192 |
+
Home & Garden > Decor > Window Treatment Accessories > Curtain & Drape Rings
|
3193 |
+
Home & Garden > Decor > Window Treatment Accessories > Curtain & Drape Rods
|
3194 |
+
Home & Garden > Decor > Window Treatment Accessories > Curtain Holdbacks & Tassels
|
3195 |
+
Home & Garden > Decor > Window Treatment Accessories > Window Treatment Replacement Parts
|
3196 |
+
Home & Garden > Decor > Window Treatments
|
3197 |
+
Home & Garden > Decor > Window Treatments > Curtains & Drapes
|
3198 |
+
Home & Garden > Decor > Window Treatments > Stained Glass Panels
|
3199 |
+
Home & Garden > Decor > Window Treatments > Window Blinds & Shades
|
3200 |
+
Home & Garden > Decor > Window Treatments > Window Films
|
3201 |
+
Home & Garden > Decor > Window Treatments > Window Screens
|
3202 |
+
Home & Garden > Decor > Window Treatments > Window Valances & Cornices
|
3203 |
+
Home & Garden > Decor > World Globes
|
3204 |
+
Home & Garden > Decor > Wreaths & Garlands
|
3205 |
+
Home & Garden > Emergency Preparedness
|
3206 |
+
Home & Garden > Emergency Preparedness > Earthquake Alarms
|
3207 |
+
Home & Garden > Emergency Preparedness > Emergency Blankets
|
3208 |
+
Home & Garden > Emergency Preparedness > Emergency Food Kits
|
3209 |
+
Home & Garden > Emergency Preparedness > Emergency Tools & Kits
|
3210 |
+
Home & Garden > Emergency Preparedness > Furniture Anchors
|
3211 |
+
Home & Garden > Fireplace & Wood Stove Accessories
|
3212 |
+
Home & Garden > Fireplace & Wood Stove Accessories > Bellows
|
3213 |
+
Home & Garden > Fireplace & Wood Stove Accessories > Fireplace & Wood Stove Grates
|
3214 |
+
Home & Garden > Fireplace & Wood Stove Accessories > Fireplace Andirons
|
3215 |
+
Home & Garden > Fireplace & Wood Stove Accessories > Fireplace Reflectors
|
3216 |
+
Home & Garden > Fireplace & Wood Stove Accessories > Fireplace Screens
|
3217 |
+
Home & Garden > Fireplace & Wood Stove Accessories > Fireplace Tools
|
3218 |
+
Home & Garden > Fireplace & Wood Stove Accessories > Firewood & Fuel
|
3219 |
+
Home & Garden > Fireplace & Wood Stove Accessories > Hearth Pads
|
3220 |
+
Home & Garden > Fireplace & Wood Stove Accessories > Log Rack & Carrier Accessories
|
3221 |
+
Home & Garden > Fireplace & Wood Stove Accessories > Log Racks & Carriers
|
3222 |
+
Home & Garden > Fireplace & Wood Stove Accessories > Wood Stove Fans & Blowers
|
3223 |
+
Home & Garden > Fireplaces
|
3224 |
+
Home & Garden > Flood, Fire & Gas Safety
|
3225 |
+
Home & Garden > Flood, Fire & Gas Safety > Fire Alarm Control Panels
|
3226 |
+
Home & Garden > Flood, Fire & Gas Safety > Fire Alarms
|
3227 |
+
Home & Garden > Flood, Fire & Gas Safety > Fire Extinguisher & Equipment Storage
|
3228 |
+
Home & Garden > Flood, Fire & Gas Safety > Fire Extinguishers
|
3229 |
+
Home & Garden > Flood, Fire & Gas Safety > Fire Sprinklers
|
3230 |
+
Home & Garden > Flood, Fire & Gas Safety > Heat Detectors
|
3231 |
+
Home & Garden > Flood, Fire & Gas Safety > Smoke & Carbon Monoxide Detectors
|
3232 |
+
Home & Garden > Flood, Fire & Gas Safety > Smoke & Carbon Monoxide Detectors > Carbon Monoxide Detectors
|
3233 |
+
Home & Garden > Flood, Fire & Gas Safety > Smoke & Carbon Monoxide Detectors > Smoke Detectors
|
3234 |
+
Home & Garden > Flood, Fire & Gas Safety > Water & Flood Detectors
|
3235 |
+
Home & Garden > Household Appliance Accessories
|
3236 |
+
Home & Garden > Household Appliance Accessories > Air Conditioner Accessories
|
3237 |
+
Home & Garden > Household Appliance Accessories > Air Conditioner Accessories > Air Conditioner Covers
|
3238 |
+
Home & Garden > Household Appliance Accessories > Air Conditioner Accessories > Air Conditioner Filters
|
3239 |
+
Home & Garden > Household Appliance Accessories > Air Purifier Accessories
|
3240 |
+
Home & Garden > Household Appliance Accessories > Air Purifier Accessories > Air Purifier Filters
|
3241 |
+
Home & Garden > Household Appliance Accessories > Dehumidifier Accessories
|
3242 |
+
Home & Garden > Household Appliance Accessories > Fan Accessories
|
3243 |
+
Home & Garden > Household Appliance Accessories > Floor & Steam Cleaner Accessories
|
3244 |
+
Home & Garden > Household Appliance Accessories > Furnace & Boiler Accessories
|
3245 |
+
Home & Garden > Household Appliance Accessories > Heating Radiator Accessories
|
3246 |
+
Home & Garden > Household Appliance Accessories > Heating Radiator Accessories > Heating Radiator Reflectors
|
3247 |
+
Home & Garden > Household Appliance Accessories > Humidifier Accessories
|
3248 |
+
Home & Garden > Household Appliance Accessories > Humidifier Accessories > Humidifier Filters
|
3249 |
+
Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories
|
3250 |
+
Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories > Garment Steamer Accessories
|
3251 |
+
Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories > Iron Accessories
|
3252 |
+
Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories > Steam Press Accessories
|
3253 |
+
Home & Garden > Household Appliance Accessories > Laundry Appliance Accessories > Washer & Dryer Accessories
|
3254 |
+
Home & Garden > Household Appliance Accessories > Patio Heater Accessories
|
3255 |
+
Home & Garden > Household Appliance Accessories > Patio Heater Accessories > Patio Heater Covers
|
3256 |
+
Home & Garden > Household Appliance Accessories > Vacuum Accessories
|
3257 |
+
Home & Garden > Household Appliance Accessories > Water Heater Accessories
|
3258 |
+
Home & Garden > Household Appliance Accessories > Water Heater Accessories > Anode Rods
|
3259 |
+
Home & Garden > Household Appliance Accessories > Water Heater Accessories > Hot Water Tanks
|
3260 |
+
Home & Garden > Household Appliance Accessories > Water Heater Accessories > Water Heater Elements
|
3261 |
+
Home & Garden > Household Appliance Accessories > Water Heater Accessories > Water Heater Expansion Tanks
|
3262 |
+
Home & Garden > Household Appliance Accessories > Water Heater Accessories > Water Heater Pans
|
3263 |
+
Home & Garden > Household Appliance Accessories > Water Heater Accessories > Water Heater Stacks
|
3264 |
+
Home & Garden > Household Appliance Accessories > Water Heater Accessories > Water Heater Vents
|
3265 |
+
Home & Garden > Household Appliances
|
3266 |
+
Home & Garden > Household Appliances > Climate Control Appliances
|
3267 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Air Conditioners
|
3268 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Air Purifiers
|
3269 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Dehumidifiers
|
3270 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Duct Heaters
|
3271 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Evaporative Coolers
|
3272 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Fans
|
3273 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Fans > Ceiling Fans
|
3274 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Fans > Desk & Pedestal Fans
|
3275 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Fans > Powered Hand Fans & Misters
|
3276 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Fans > Ventilation Fans
|
3277 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Fans > Wall Mount Fans
|
3278 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Furnaces & Boilers
|
3279 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Heating Radiators
|
3280 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Humidifiers
|
3281 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Outdoor Misting Systems
|
3282 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Patio Heaters
|
3283 |
+
Home & Garden > Household Appliances > Climate Control Appliances > Space Heaters
|
3284 |
+
Home & Garden > Household Appliances > Floor & Carpet Dryers
|
3285 |
+
Home & Garden > Household Appliances > Floor & Steam Cleaners
|
3286 |
+
Home & Garden > Household Appliances > Floor & Steam Cleaners > Carpet Shampooers
|
3287 |
+
Home & Garden > Household Appliances > Floor & Steam Cleaners > Carpet Steamers
|
3288 |
+
Home & Garden > Household Appliances > Floor & Steam Cleaners > Floor Scrubbers
|
3289 |
+
Home & Garden > Household Appliances > Floor & Steam Cleaners > Steam Mops
|
3290 |
+
Home & Garden > Household Appliances > Floor Polishers & Buffers
|
3291 |
+
Home & Garden > Household Appliances > Futon Dryers
|
3292 |
+
Home & Garden > Household Appliances > Garage Door Keypads & Remotes
|
3293 |
+
Home & Garden > Household Appliances > Garage Door Openers
|
3294 |
+
Home & Garden > Household Appliances > Laundry Appliances
|
3295 |
+
Home & Garden > Household Appliances > Laundry Appliances > Dryers
|
3296 |
+
Home & Garden > Household Appliances > Laundry Appliances > Garment Steamers
|
3297 |
+
Home & Garden > Household Appliances > Laundry Appliances > Irons & Ironing Systems
|
3298 |
+
Home & Garden > Household Appliances > Laundry Appliances > Laundry Combo Units
|
3299 |
+
Home & Garden > Household Appliances > Laundry Appliances > Steam Presses
|
3300 |
+
Home & Garden > Household Appliances > Laundry Appliances > Washing Machines
|
3301 |
+
Home & Garden > Household Appliances > Ultrasonic Cleaners
|
3302 |
+
Home & Garden > Household Appliances > Vacuums
|
3303 |
+
Home & Garden > Household Appliances > Wallpaper Steamers
|
3304 |
+
Home & Garden > Household Appliances > Water Heaters
|
3305 |
+
Home & Garden > Household Supplies
|
3306 |
+
Home & Garden > Household Supplies > Drawer & Shelf Liners
|
3307 |
+
Home & Garden > Household Supplies > Floor Protection Films & Runners
|
3308 |
+
Home & Garden > Household Supplies > Furniture Floor Protectors
|
3309 |
+
Home & Garden > Household Supplies > Garage Floor Mats
|
3310 |
+
Home & Garden > Household Supplies > Garbage Bags
|
3311 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies
|
3312 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Broom & Mop Handles
|
3313 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Broom Heads
|
3314 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Brooms
|
3315 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Buckets
|
3316 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Carpet Sweepers
|
3317 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Cleaning Gloves
|
3318 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Duster Refills
|
3319 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Dusters
|
3320 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Dustpans
|
3321 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Fabric & Upholstery Protectors
|
3322 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products
|
3323 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > All-Purpose Cleaners
|
3324 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Carpet Cleaners
|
3325 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Descalers & Decalcifiers
|
3326 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Dish Detergent & Soap
|
3327 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Dishwasher Cleaners
|
3328 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Fabric & Upholstery Cleaners
|
3329 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Floor Cleaners
|
3330 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Furniture Cleaners & Polish
|
3331 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Glass & Surface Cleaners
|
3332 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Glass & Surface Cleaners > Glass Cleaners
|
3333 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Glass & Surface Cleaners > Muti-surface Cleaners
|
3334 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Household Disinfectants
|
3335 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Oven & Grill Cleaners
|
3336 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Pet Odor & Stain Removers
|
3337 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Rinse Aids
|
3338 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Stainless Steel Cleaners & Polishes
|
3339 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Toilet Bowl Cleaners
|
3340 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Tub & Tile Cleaners
|
3341 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Household Cleaning Products > Washing Machine Cleaners
|
3342 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Mop Heads & Refills
|
3343 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Mops
|
3344 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Scrub Brush Heads & Refills
|
3345 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Scrub Brushes
|
3346 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Shop Towels & General-Purpose Cleaning Cloths
|
3347 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Sponges & Scouring Pads
|
3348 |
+
Home & Garden > Household Supplies > Household Cleaning Supplies > Squeegees
|
3349 |
+
Home & Garden > Household Supplies > Household Paper Products
|
3350 |
+
Home & Garden > Household Supplies > Household Paper Products > Facial Tissues
|
3351 |
+
Home & Garden > Household Supplies > Household Paper Products > Paper Napkins
|
3352 |
+
Home & Garden > Household Supplies > Household Paper Products > Paper Towels
|
3353 |
+
Home & Garden > Household Supplies > Household Paper Products > Toilet Paper
|
3354 |
+
Home & Garden > Household Supplies > Household Thermometers
|
3355 |
+
Home & Garden > Household Supplies > Laundry Supplies
|
3356 |
+
Home & Garden > Household Supplies > Laundry Supplies > Bleach
|
3357 |
+
Home & Garden > Household Supplies > Laundry Supplies > Clothespins
|
3358 |
+
Home & Garden > Household Supplies > Laundry Supplies > Dry Cleaning Kits
|
3359 |
+
Home & Garden > Household Supplies > Laundry Supplies > Drying Racks & Hangers
|
3360 |
+
Home & Garden > Household Supplies > Laundry Supplies > Fabric Refreshers
|
3361 |
+
Home & Garden > Household Supplies > Laundry Supplies > Fabric Shavers
|
3362 |
+
Home & Garden > Household Supplies > Laundry Supplies > Fabric Softeners & Dryer Sheets
|
3363 |
+
Home & Garden > Household Supplies > Laundry Supplies > Fabric Stain Removers
|
3364 |
+
Home & Garden > Household Supplies > Laundry Supplies > Fabric Starch
|
3365 |
+
Home & Garden > Household Supplies > Laundry Supplies > Garment Shields
|
3366 |
+
Home & Garden > Household Supplies > Laundry Supplies > Iron Rests
|
3367 |
+
Home & Garden > Household Supplies > Laundry Supplies > Ironing Board Pads & Covers
|
3368 |
+
Home & Garden > Household Supplies > Laundry Supplies > Ironing Board Replacement Parts
|
3369 |
+
Home & Garden > Household Supplies > Laundry Supplies > Ironing Boards
|
3370 |
+
Home & Garden > Household Supplies > Laundry Supplies > Laundry Balls
|
3371 |
+
Home & Garden > Household Supplies > Laundry Supplies > Laundry Baskets
|
3372 |
+
Home & Garden > Household Supplies > Laundry Supplies > Laundry Detergent
|
3373 |
+
Home & Garden > Household Supplies > Laundry Supplies > Laundry Wash Bags & Frames
|
3374 |
+
Home & Garden > Household Supplies > Laundry Supplies > Lint Rollers
|
3375 |
+
Home & Garden > Household Supplies > Laundry Supplies > Wrinkle Releasers & Anti-Static Sprays
|
3376 |
+
Home & Garden > Household Supplies > Moisture Absorbers
|
3377 |
+
Home & Garden > Household Supplies > Pest Control
|
3378 |
+
Home & Garden > Household Supplies > Pest Control > Fly Swatters
|
3379 |
+
Home & Garden > Household Supplies > Pest Control > Pest Control Traps
|
3380 |
+
Home & Garden > Household Supplies > Pest Control > Pesticides
|
3381 |
+
Home & Garden > Household Supplies > Pest Control > Repellents
|
3382 |
+
Home & Garden > Household Supplies > Pest Control > Repellents > Animal & Pet Repellents
|
3383 |
+
Home & Garden > Household Supplies > Pest Control > Repellents > Household Insect Repellents
|
3384 |
+
Home & Garden > Household Supplies > Rug Pads
|
3385 |
+
Home & Garden > Household Supplies > Shoe Care & Tools
|
3386 |
+
Home & Garden > Household Supplies > Shoe Care & Tools > Boot Pulls
|
3387 |
+
Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Bags
|
3388 |
+
Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Brushes
|
3389 |
+
Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Care Kits
|
3390 |
+
Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Dryers
|
3391 |
+
Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Horns & Dressing Aids
|
3392 |
+
Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Polishers
|
3393 |
+
Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Polishes & Waxes
|
3394 |
+
Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Scrapers
|
3395 |
+
Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Treatments & Dyes
|
3396 |
+
Home & Garden > Household Supplies > Shoe Care & Tools > Shoe Trees & Shapers
|
3397 |
+
Home & Garden > Household Supplies > Stair Treads
|
3398 |
+
Home & Garden > Household Supplies > Storage & Organization
|
3399 |
+
Home & Garden > Household Supplies > Storage & Organization > Clothing & Closet Storage
|
3400 |
+
Home & Garden > Household Supplies > Storage & Organization > Clothing & Closet Storage > Charging Valets
|
3401 |
+
Home & Garden > Household Supplies > Storage & Organization > Clothing & Closet Storage > Closet Organizers & Garment Racks
|
3402 |
+
Home & Garden > Household Supplies > Storage & Organization > Clothing & Closet Storage > Clothes Valets
|
3403 |
+
Home & Garden > Household Supplies > Storage & Organization > Clothing & Closet Storage > Hangers
|
3404 |
+
Home & Garden > Household Supplies > Storage & Organization > Clothing & Closet Storage > Hat Boxes
|
3405 |
+
Home & Garden > Household Supplies > Storage & Organization > Clothing & Closet Storage > Shoe Racks & Organizers
|
3406 |
+
Home & Garden > Household Supplies > Storage & Organization > Flatware Chests
|
3407 |
+
Home & Garden > Household Supplies > Storage & Organization > Household Drawer Organizer Inserts
|
3408 |
+
Home & Garden > Household Supplies > Storage & Organization > Household Storage Bags
|
3409 |
+
Home & Garden > Household Supplies > Storage & Organization > Household Storage Caddies
|
3410 |
+
Home & Garden > Household Supplies > Storage & Organization > Household Storage Containers
|
3411 |
+
Home & Garden > Household Supplies > Storage & Organization > Household Storage Drawers
|
3412 |
+
Home & Garden > Household Supplies > Storage & Organization > Photo Storage
|
3413 |
+
Home & Garden > Household Supplies > Storage & Organization > Photo Storage > Photo Albums
|
3414 |
+
Home & Garden > Household Supplies > Storage & Organization > Photo Storage > Photo Storage Boxes
|
3415 |
+
Home & Garden > Household Supplies > Storage & Organization > Storage Hooks & Racks
|
3416 |
+
Home & Garden > Household Supplies > Storage & Organization > Storage Hooks & Racks > Ironing Board Hooks & Racks
|
3417 |
+
Home & Garden > Household Supplies > Storage & Organization > Storage Hooks & Racks > Umbrella Stands & Racks
|
3418 |
+
Home & Garden > Household Supplies > Storage & Organization > Storage Hooks & Racks > Utility Hooks
|
3419 |
+
Home & Garden > Household Supplies > Trash Compactor Accessories
|
3420 |
+
Home & Garden > Household Supplies > Waste Containment
|
3421 |
+
Home & Garden > Household Supplies > Waste Containment > Dumpsters
|
3422 |
+
Home & Garden > Household Supplies > Waste Containment > Hazardous Waste Containers
|
3423 |
+
Home & Garden > Household Supplies > Waste Containment > Recycling Containers
|
3424 |
+
Home & Garden > Household Supplies > Waste Containment > Trash Cans & Wastebaskets
|
3425 |
+
Home & Garden > Household Supplies > Waste Containment Accessories
|
3426 |
+
Home & Garden > Household Supplies > Waste Containment Accessories > Waste Container Carts
|
3427 |
+
Home & Garden > Household Supplies > Waste Containment Accessories > Waste Container Enclosures
|
3428 |
+
Home & Garden > Household Supplies > Waste Containment Accessories > Waste Container Labels & Signs
|
3429 |
+
Home & Garden > Household Supplies > Waste Containment Accessories > Waste Container Lids
|
3430 |
+
Home & Garden > Household Supplies > Waste Containment Accessories > Waste Container Wheels
|
3431 |
+
Home & Garden > Kitchen & Dining
|
3432 |
+
Home & Garden > Kitchen & Dining > Barware
|
3433 |
+
Home & Garden > Kitchen & Dining > Barware > Absinthe Fountains
|
3434 |
+
Home & Garden > Kitchen & Dining > Barware > Beer Dispensers & Taps
|
3435 |
+
Home & Garden > Kitchen & Dining > Barware > Beverage Chilling Cubes & Sticks
|
3436 |
+
Home & Garden > Kitchen & Dining > Barware > Beverage Tubs & Chillers
|
3437 |
+
Home & Garden > Kitchen & Dining > Barware > Bottle Caps
|
3438 |
+
Home & Garden > Kitchen & Dining > Barware > Bottle Stoppers & Savers
|
3439 |
+
Home & Garden > Kitchen & Dining > Barware > Coaster Holders
|
3440 |
+
Home & Garden > Kitchen & Dining > Barware > Coasters
|
3441 |
+
Home & Garden > Kitchen & Dining > Barware > Cocktail & Barware Tool Sets
|
3442 |
+
Home & Garden > Kitchen & Dining > Barware > Cocktail Shakers & Tools
|
3443 |
+
Home & Garden > Kitchen & Dining > Barware > Cocktail Shakers & Tools > Bar Ice Picks
|
3444 |
+
Home & Garden > Kitchen & Dining > Barware > Cocktail Shakers & Tools > Bottle Openers
|
3445 |
+
Home & Garden > Kitchen & Dining > Barware > Cocktail Shakers & Tools > Cocktail Shakers
|
3446 |
+
Home & Garden > Kitchen & Dining > Barware > Cocktail Shakers & Tools > Cocktail Strainers
|
3447 |
+
Home & Garden > Kitchen & Dining > Barware > Cocktail Shakers & Tools > Muddlers
|
3448 |
+
Home & Garden > Kitchen & Dining > Barware > Corkscrews
|
3449 |
+
Home & Garden > Kitchen & Dining > Barware > Decanters
|
3450 |
+
Home & Garden > Kitchen & Dining > Barware > Foil Cutters
|
3451 |
+
Home & Garden > Kitchen & Dining > Barware > Wine Aerators
|
3452 |
+
Home & Garden > Kitchen & Dining > Barware > Wine Bottle Holders
|
3453 |
+
Home & Garden > Kitchen & Dining > Barware > Wine Glass Charms
|
3454 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware
|
3455 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware
|
3456 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Bakeware Sets
|
3457 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Baking & Cookie Sheets
|
3458 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Bread Pans & Molds
|
3459 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Broiling Pans
|
3460 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Cake Pans & Molds
|
3461 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Muffin & Pastry Pans
|
3462 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Pie & Quiche Pans
|
3463 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Pizza Pans
|
3464 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Pizza Stones
|
3465 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Ramekins & Souffle Dishes
|
3466 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware > Roasting Pans
|
3467 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware Accessories
|
3468 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware Accessories > Baking Mats & Liners
|
3469 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware Accessories > Baking Weights
|
3470 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Bakeware Accessories > Roasting Pan Racks
|
3471 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware
|
3472 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware & Bakeware Combo Sets
|
3473 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Casserole Dishes
|
3474 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Cookware Sets
|
3475 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Crêpe & Blini Pans
|
3476 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Double Boilers
|
3477 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Dutch Ovens
|
3478 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Fermentation & Pickling Crocks
|
3479 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Griddles & Grill Pans
|
3480 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Grill Presses
|
3481 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Paella Pans
|
3482 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Pressure Cookers & Canners
|
3483 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Saucepans
|
3484 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Sauté Pans
|
3485 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Skillets & Frying Pans
|
3486 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Stock Pots
|
3487 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Stovetop Kettles
|
3488 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Tagines & Clay Cooking Pots
|
3489 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware > Woks
|
3490 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories
|
3491 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories > Pot & Pan Handles
|
3492 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories > Pot & Pan Lids
|
3493 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories > Pressure Cooker & Canner Accessories
|
3494 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories > Steamer Baskets
|
3495 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories > Wok Accessories
|
3496 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories > Wok Accessories > Wok Brushes
|
3497 |
+
Home & Garden > Kitchen & Dining > Cookware & Bakeware > Cookware Accessories > Wok Accessories > Wok Rings
|
3498 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers
|
3499 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Airpots
|
3500 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Canteens
|
3501 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Coolers
|
3502 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Drink Sleeves
|
3503 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Drink Sleeves > Can & Bottle Sleeves
|
3504 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Drink Sleeves > Cup Sleeves
|
3505 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Flasks
|
3506 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Insulated Bags
|
3507 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Lunch Boxes & Totes
|
3508 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Picnic Baskets
|
3509 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Replacement Drink Lids
|
3510 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Thermoses
|
3511 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Water Bottles
|
3512 |
+
Home & Garden > Kitchen & Dining > Food & Beverage Carriers > Wine Carrier Bags
|
3513 |
+
Home & Garden > Kitchen & Dining > Food Storage
|
3514 |
+
Home & Garden > Kitchen & Dining > Food Storage > Bread Boxes & Bags
|
3515 |
+
Home & Garden > Kitchen & Dining > Food Storage > Candy Buckets
|
3516 |
+
Home & Garden > Kitchen & Dining > Food Storage > Cookie Jars
|
3517 |
+
Home & Garden > Kitchen & Dining > Food Storage > Food Container Covers
|
3518 |
+
Home & Garden > Kitchen & Dining > Food Storage > Food Storage Bags
|
3519 |
+
Home & Garden > Kitchen & Dining > Food Storage > Food Storage Containers
|
3520 |
+
Home & Garden > Kitchen & Dining > Food Storage > Food Wraps
|
3521 |
+
Home & Garden > Kitchen & Dining > Food Storage > Food Wraps > Foil
|
3522 |
+
Home & Garden > Kitchen & Dining > Food Storage > Food Wraps > Parchment Paper
|
3523 |
+
Home & Garden > Kitchen & Dining > Food Storage > Food Wraps > Plastic Wrap
|
3524 |
+
Home & Garden > Kitchen & Dining > Food Storage > Food Wraps > Wax Paper
|
3525 |
+
Home & Garden > Kitchen & Dining > Food Storage > Honey Jars
|
3526 |
+
Home & Garden > Kitchen & Dining > Food Storage Accessories
|
3527 |
+
Home & Garden > Kitchen & Dining > Food Storage Accessories > Food & Beverage Labels
|
3528 |
+
Home & Garden > Kitchen & Dining > Food Storage Accessories > Food Wrap Dispensers
|
3529 |
+
Home & Garden > Kitchen & Dining > Food Storage Accessories > Oxygen Absorbers
|
3530 |
+
Home & Garden > Kitchen & Dining > Food Storage Accessories > Twist Ties & Bag Clips
|
3531 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories
|
3532 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Breadmaker Accessories
|
3533 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories
|
3534 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Decanter Warmers
|
3535 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Decanters
|
3536 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Filter Baskets
|
3537 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Filters
|
3538 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Grinder Accessories
|
3539 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Grinders
|
3540 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Maker & Espresso Machine Replacement Parts
|
3541 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Coffee Maker Water Filters
|
3542 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Frothing Pitchers
|
3543 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Coffee Maker & Espresso Machine Accessories > Portafilters
|
3544 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Cooktop, Oven & Range Accessories
|
3545 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Cotton Candy Machine Accessories
|
3546 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Deep Fryer Accessories
|
3547 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Dishwasher Parts & Accessories
|
3548 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Electric Kettle Accessories
|
3549 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Electric Skillet & Wok Accessories
|
3550 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Fondue Set Accessories
|
3551 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Fondue Set Accessories > Cooking Gel Fuels
|
3552 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Fondue Set Accessories > Fondue Forks
|
3553 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Fondue Set Accessories > Fondue Pot Stands
|
3554 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Dehydrator Accessories
|
3555 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Dehydrator Accessories > Food Dehydrator Sheets
|
3556 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Dehydrator Accessories > Food Dehydrator Trays
|
3557 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Grinder Accessories
|
3558 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Food Mixer & Blender Accessories
|
3559 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Freezer Accessories
|
3560 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Garbage Disposal Accessories
|
3561 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Ice Cream Maker Accessories
|
3562 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Ice Cream Maker Accessories > Ice Cream Maker Freezer Bowls
|
3563 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Ice Crusher & Shaver Accessories
|
3564 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Ice Maker Accessories
|
3565 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Juicer Accessories
|
3566 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Microwave Oven Accessories
|
3567 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories
|
3568 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Charcoal Briquettes
|
3569 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Charcoal Chimneys
|
3570 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Outdoor Grill Carts
|
3571 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Outdoor Grill Covers
|
3572 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Outdoor Grill Racks & Toppers
|
3573 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Outdoor Grill Replacement Parts
|
3574 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Outdoor Grill Spits & Baskets
|
3575 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Outdoor Grilling Planks
|
3576 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Outdoor Grill Accessories > Smoking Chips & Pellets
|
3577 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Pasta Maker Accessories
|
3578 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Popcorn Maker Accessories
|
3579 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Portable Cooking Stove Accessories
|
3580 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Range Hood Accessories
|
3581 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Refrigerator Accessories
|
3582 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Soda Maker Accessories
|
3583 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Steam Table Accessories
|
3584 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Steam Table Accessories > Steam Table Pan Covers
|
3585 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Steam Table Accessories > Steam Table Pans
|
3586 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Toaster Accessories
|
3587 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Vacuum Sealer Accessories
|
3588 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Vacuum Sealer Accessories > Vacuum Sealer Bags
|
3589 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Waffle Iron Accessories
|
3590 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Water Cooler Accessories
|
3591 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Water Cooler Accessories > Water Cooler Bottles
|
3592 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Wine Fridge Accessories
|
3593 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliance Accessories > Yogurt Maker Accessories
|
3594 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances
|
3595 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Beverage Warmers
|
3596 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Breadmakers
|
3597 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Chocolate Tempering Machines
|
3598 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Coffee Makers & Espresso Machines
|
3599 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Coffee Makers & Espresso Machines > Drip Coffee Makers
|
3600 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Coffee Makers & Espresso Machines > Electric & Stovetop Espresso Pots
|
3601 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Coffee Makers & Espresso Machines > Espresso Machines
|
3602 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Coffee Makers & Espresso Machines > French Presses
|
3603 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Coffee Makers & Espresso Machines > Percolators
|
3604 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Coffee Makers & Espresso Machines > Vacuum Coffee Makers
|
3605 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Cooktops
|
3606 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Cotton Candy Machines
|
3607 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Deep Fryers
|
3608 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Deli Slicers
|
3609 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Dishwashers
|
3610 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Electric Griddles & Grills
|
3611 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Electric Kettles
|
3612 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Electric Skillets & Woks
|
3613 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Fondue Pots & Sets
|
3614 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Cookers & Steamers
|
3615 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Cookers & Steamers > Egg Cookers
|
3616 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Cookers & Steamers > Food Steamers
|
3617 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Cookers & Steamers > Rice Cookers
|
3618 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Cookers & Steamers > Slow Cookers
|
3619 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Cookers & Steamers > Thermal Cookers
|
3620 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Cookers & Steamers > Water Ovens
|
3621 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Dehydrators
|
3622 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Grinders & Mills
|
3623 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Mixers & Blenders
|
3624 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Smokers
|
3625 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Warmers
|
3626 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Warmers > Chafing Dishes
|
3627 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Warmers > Food Heat Lamps
|
3628 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Warmers > Rice Keepers
|
3629 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Food Warmers > Steam Tables
|
3630 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Freezers
|
3631 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Frozen Drink Makers
|
3632 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Garbage Disposals
|
3633 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Gas Griddles
|
3634 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Hot Drink Makers
|
3635 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Hot Plates
|
3636 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Ice Cream Makers
|
3637 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Ice Crushers & Shavers
|
3638 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Ice Makers
|
3639 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Juicers
|
3640 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Knife Sharpeners
|
3641 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Microwave Ovens
|
3642 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Milk Frothers & Steamers
|
3643 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Mochi Makers
|
3644 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Outdoor Grills
|
3645 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Ovens
|
3646 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Pasta Makers
|
3647 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Popcorn Makers
|
3648 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Portable Cooking Stoves
|
3649 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Range Hoods
|
3650 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Ranges
|
3651 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Refrigerators
|
3652 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Roaster Ovens & Rotisseries
|
3653 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Soda Makers
|
3654 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Soy Milk Makers
|
3655 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Tea Makers
|
3656 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills
|
3657 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Countertop & Toaster Ovens
|
3658 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Donut Makers
|
3659 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Muffin & Cupcake Makers
|
3660 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Pizza Makers & Ovens
|
3661 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Pizzelle Makers
|
3662 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Pretzel Makers
|
3663 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Sandwich Makers
|
3664 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Toasters
|
3665 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Tortilla & Flatbread Makers
|
3666 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Toasters & Grills > Waffle Irons
|
3667 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Trash Compactors
|
3668 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Vacuum Sealers
|
3669 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Water Coolers
|
3670 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Water Filters
|
3671 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Wine Fridges
|
3672 |
+
Home & Garden > Kitchen & Dining > Kitchen Appliances > Yogurt Makers
|
3673 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils
|
3674 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Aprons
|
3675 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Baking Peels
|
3676 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Basters
|
3677 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Basting Brushes
|
3678 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Beverage Dispensers
|
3679 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cake Decorating Supplies
|
3680 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cake Servers
|
3681 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Can Crushers
|
3682 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Can Openers
|
3683 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Carving Forks
|
3684 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Channel Knives
|
3685 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Colanders & Strainers
|
3686 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Condiment Dispensers
|
3687 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cookie Cutters
|
3688 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cookie Presses
|
3689 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cooking Thermometer Accessories
|
3690 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cooking Thermometers
|
3691 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cooking Timers
|
3692 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cooking Torches
|
3693 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cooling Racks
|
3694 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Cutting Boards
|
3695 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Dish Racks & Drain Boards
|
3696 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Dough Wheels
|
3697 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Electric Knife Accessories
|
3698 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Electric Knife Accessories > Electric Knife Replacement Blades
|
3699 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Electric Knives
|
3700 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Flour Sifters
|
3701 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food & Drink Stencils
|
3702 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Crackers
|
3703 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Crackers > Lobster & Crab Crackers
|
3704 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Crackers > Nutcrackers
|
3705 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Crackers > Nutcrackers > Decorative Nutcrackers
|
3706 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Dispensers
|
3707 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Graters & Zesters
|
3708 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Peelers & Corers
|
3709 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Steaming Bags
|
3710 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Food Sticks & Skewers
|
3711 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Funnels
|
3712 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Garlic Presses
|
3713 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Gelatin Molds
|
3714 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Ice Cube Trays
|
3715 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Jerky Guns
|
3716 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Knives
|
3717 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Molds
|
3718 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers
|
3719 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Can Organizers
|
3720 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Drinkware Holders
|
3721 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Kitchen Cabinet Organizers
|
3722 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Kitchen Counter & Beverage Station Organizers
|
3723 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Kitchen Utensil Holders & Racks
|
3724 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Knife Blocks & Holders
|
3725 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Napkin Holders & Dispensers
|
3726 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Paper Towel Holders & Dispensers
|
3727 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Pot Racks
|
3728 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Spice Organizers
|
3729 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Straw Holders & Dispensers
|
3730 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Sugar Caddies
|
3731 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Toothpick Holders & Dispensers
|
3732 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Organizers > Utensil & Flatware Trays
|
3733 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Scrapers
|
3734 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Scrapers > Bench Scrapers
|
3735 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Scrapers > Bowl Scrapers
|
3736 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Scrapers > Grill Scrapers
|
3737 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Shears
|
3738 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Slicers
|
3739 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Kitchen Utensil Sets
|
3740 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Ladles
|
3741 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Mashers
|
3742 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Measuring Cups & Spoons
|
3743 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Meat Tenderizers
|
3744 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Mixing Bowls
|
3745 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Mortars & Pestles
|
3746 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Oil & Vinegar Dispensers
|
3747 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Oven Bags
|
3748 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Oven Mitts & Pot Holders
|
3749 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Pasta Molds & Stamps
|
3750 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Pastry Blenders
|
3751 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Pastry Cloths
|
3752 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Pizza Cutter Accessories
|
3753 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Pizza Cutters
|
3754 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Ricers
|
3755 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Rolling Pin Accessories
|
3756 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Rolling Pin Accessories > Rolling Pin Covers & Sleeves
|
3757 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Rolling Pin Accessories > Rolling Pin Rings
|
3758 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Rolling Pins
|
3759 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Salad Dressing Mixers & Shakers
|
3760 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Salad Spinners
|
3761 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Scoops
|
3762 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Scoops > Ice Cream Scoops
|
3763 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Scoops > Ice Scoops
|
3764 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Scoops > Melon Ballers
|
3765 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Scoops > Popcorn & French Fry Scoops
|
3766 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Sink Caddies
|
3767 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Sink Mats & Grids
|
3768 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Slotted Spoons
|
3769 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Spatulas
|
3770 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Spice Grinder Accessories
|
3771 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Spice Grinders
|
3772 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Spoon Rests
|
3773 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Sugar Dispensers
|
3774 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Sushi Mats
|
3775 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Tea Strainers
|
3776 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Tongs
|
3777 |
+
Home & Garden > Kitchen & Dining > Kitchen Tools & Utensils > Whisks
|
3778 |
+
Home & Garden > Kitchen & Dining > Prefabricated Kitchens & Kitchenettes
|
3779 |
+
Home & Garden > Kitchen & Dining > Tableware
|
3780 |
+
Home & Garden > Kitchen & Dining > Tableware > Coffee & Tea Sets
|
3781 |
+
Home & Garden > Kitchen & Dining > Tableware > Coffee Servers & Tea Pots
|
3782 |
+
Home & Garden > Kitchen & Dining > Tableware > Dinnerware
|
3783 |
+
Home & Garden > Kitchen & Dining > Tableware > Dinnerware > Bowls
|
3784 |
+
Home & Garden > Kitchen & Dining > Tableware > Dinnerware > Dinnerware Sets
|
3785 |
+
Home & Garden > Kitchen & Dining > Tableware > Dinnerware > Plates
|
3786 |
+
Home & Garden > Kitchen & Dining > Tableware > Drinkware
|
3787 |
+
Home & Garden > Kitchen & Dining > Tableware > Drinkware > Beer Glasses
|
3788 |
+
Home & Garden > Kitchen & Dining > Tableware > Drinkware > Coffee & Tea Cups
|
3789 |
+
Home & Garden > Kitchen & Dining > Tableware > Drinkware > Coffee & Tea Saucers
|
3790 |
+
Home & Garden > Kitchen & Dining > Tableware > Drinkware > Drinkware Sets
|
3791 |
+
Home & Garden > Kitchen & Dining > Tableware > Drinkware > Mugs
|
3792 |
+
Home & Garden > Kitchen & Dining > Tableware > Drinkware > Shot Glasses
|
3793 |
+
Home & Garden > Kitchen & Dining > Tableware > Drinkware > Stemware
|
3794 |
+
Home & Garden > Kitchen & Dining > Tableware > Drinkware > Tumblers
|
3795 |
+
Home & Garden > Kitchen & Dining > Tableware > Flatware
|
3796 |
+
Home & Garden > Kitchen & Dining > Tableware > Flatware > Chopstick Accessories
|
3797 |
+
Home & Garden > Kitchen & Dining > Tableware > Flatware > Chopsticks
|
3798 |
+
Home & Garden > Kitchen & Dining > Tableware > Flatware > Flatware Sets
|
3799 |
+
Home & Garden > Kitchen & Dining > Tableware > Flatware > Forks
|
3800 |
+
Home & Garden > Kitchen & Dining > Tableware > Flatware > Spoons
|
3801 |
+
Home & Garden > Kitchen & Dining > Tableware > Flatware > Table Knives
|
3802 |
+
Home & Garden > Kitchen & Dining > Tableware > Salt & Pepper Shakers
|
3803 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware
|
3804 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware > Butter Dishes
|
3805 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware > Cake Boards
|
3806 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware > Cake Stands
|
3807 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware > Egg Cups
|
3808 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware > Gravy Boats
|
3809 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware > Punch Bowls
|
3810 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware > Serving Pitchers & Carafes
|
3811 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware > Serving Platters
|
3812 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware > Serving Trays
|
3813 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware > Sugar Bowls & Creamers
|
3814 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware > Tureens
|
3815 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware Accessories
|
3816 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware Accessories > Punch Bowl Stands
|
3817 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware Accessories > Tureen Lids
|
3818 |
+
Home & Garden > Kitchen & Dining > Tableware > Serveware Accessories > Tureen Stands
|
3819 |
+
Home & Garden > Kitchen & Dining > Tableware > Tablecloth Clips & Weights
|
3820 |
+
Home & Garden > Kitchen & Dining > Tableware > Trivets
|
3821 |
+
Home & Garden > Lawn & Garden
|
3822 |
+
Home & Garden > Lawn & Garden > Gardening
|
3823 |
+
Home & Garden > Lawn & Garden > Gardening > Composting
|
3824 |
+
Home & Garden > Lawn & Garden > Gardening > Composting > Compost
|
3825 |
+
Home & Garden > Lawn & Garden > Gardening > Composting > Compost Aerators
|
3826 |
+
Home & Garden > Lawn & Garden > Gardening > Composting > Composters
|
3827 |
+
Home & Garden > Lawn & Garden > Gardening > Disease Control
|
3828 |
+
Home & Garden > Lawn & Garden > Gardening > Fertilizers
|
3829 |
+
Home & Garden > Lawn & Garden > Gardening > Garden Pot Saucers & Trays
|
3830 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Accessories
|
3831 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Accessories > Gardening Scooters, Seats & Kneelers
|
3832 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Accessories > Gardening Totes
|
3833 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Accessories > Potting Benches
|
3834 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tool Accessories
|
3835 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tool Accessories > Gardening Tool Handles
|
3836 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tool Accessories > Gardening Tool Heads
|
3837 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tool Accessories > Wheelbarrow Parts
|
3838 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tools
|
3839 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Bulb Planting Tools
|
3840 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Cultivating Tools
|
3841 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Gardening Forks
|
3842 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Gardening Sickles & Machetes
|
3843 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Gardening Trowels
|
3844 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Lawn & Garden Sprayers
|
3845 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Lawn Rollers
|
3846 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Pruning Saws
|
3847 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Pruning Shears
|
3848 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Rakes
|
3849 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Shovels & Spades
|
3850 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Spreaders
|
3851 |
+
Home & Garden > Lawn & Garden > Gardening > Gardening Tools > Wheelbarrows
|
3852 |
+
Home & Garden > Lawn & Garden > Gardening > Greenhouses
|
3853 |
+
Home & Garden > Lawn & Garden > Gardening > Herbicides
|
3854 |
+
Home & Garden > Lawn & Garden > Gardening > Landscape Fabric
|
3855 |
+
Home & Garden > Lawn & Garden > Gardening > Landscape Fabric Accessories
|
3856 |
+
Home & Garden > Lawn & Garden > Gardening > Landscape Fabric Accessories > Landscape Fabric Staples & Pins
|
3857 |
+
Home & Garden > Lawn & Garden > Gardening > Landscape Fabric Accessories > Landscape Fabric Tape
|
3858 |
+
Home & Garden > Lawn & Garden > Gardening > Mulch
|
3859 |
+
Home & Garden > Lawn & Garden > Gardening > Plant Cages & Supports
|
3860 |
+
Home & Garden > Lawn & Garden > Gardening > Plant Stands
|
3861 |
+
Home & Garden > Lawn & Garden > Gardening > Pot & Planter Liners
|
3862 |
+
Home & Garden > Lawn & Garden > Gardening > Pots & Planters
|
3863 |
+
Home & Garden > Lawn & Garden > Gardening > Rain Barrels
|
3864 |
+
Home & Garden > Lawn & Garden > Gardening > Sands & Soils
|
3865 |
+
Home & Garden > Lawn & Garden > Gardening > Sands & Soils > Sand
|
3866 |
+
Home & Garden > Lawn & Garden > Gardening > Sands & Soils > Soil
|
3867 |
+
Home & Garden > Lawn & Garden > Outdoor Living
|
3868 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Awning Accessories
|
3869 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Awnings
|
3870 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Hammock Parts & Accessories
|
3871 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Hammocks
|
3872 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Blankets
|
3873 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Blankets > Beach Mats
|
3874 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Blankets > Picnic Blankets
|
3875 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Blankets > Poncho Liners
|
3876 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures
|
3877 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Canopies & Gazebos
|
3878 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Canopy & Gazebo Accessories
|
3879 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Canopy & Gazebo Accessories > Canopy & Gazebo Enclosure Kits
|
3880 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Canopy & Gazebo Accessories > Canopy & Gazebo Frames
|
3881 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Canopy & Gazebo Accessories > Canopy & Gazebo Tops
|
3882 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Canopy & Gazebo Accessories > Canopy Poles
|
3883 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Canopy & Gazebo Accessories > Canopy Weights
|
3884 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Garden Arches, Trellises, Arbors & Pergolas
|
3885 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Garden Bridges
|
3886 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Structures > Sheds, Garages & Carports
|
3887 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Umbrella & Sunshade Accessories
|
3888 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Umbrella & Sunshade Accessories > Outdoor Umbrella & Sunshade Fabric
|
3889 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Umbrella & Sunshade Accessories > Outdoor Umbrella Bases
|
3890 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Umbrella & Sunshade Accessories > Outdoor Umbrella Covers
|
3891 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Umbrella & Sunshade Accessories > Outdoor Umbrella Enclosure Kits
|
3892 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Umbrella & Sunshade Accessories > Outdoor Umbrella Lights
|
3893 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Outdoor Umbrellas & Sunshades
|
3894 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Porch Swing Accessories
|
3895 |
+
Home & Garden > Lawn & Garden > Outdoor Living > Porch Swings
|
3896 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment
|
3897 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Chainsaws
|
3898 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Grass Edgers
|
3899 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Hedge Trimmers
|
3900 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Lawn Aerators & Dethatchers
|
3901 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Lawn Mowers
|
3902 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Lawn Mowers > Riding Mowers
|
3903 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Lawn Mowers > Robotic Mowers
|
3904 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Lawn Mowers > Tow-Behind Mowers
|
3905 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Lawn Mowers > Walk-Behind Mowers
|
3906 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Lawn Vacuums
|
3907 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Leaf Blowers
|
3908 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Outdoor Power Equipment Base Units
|
3909 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Outdoor Power Equipment Sets
|
3910 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Power Sweepers
|
3911 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Power Tillers & Cultivators
|
3912 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Pressure Washers
|
3913 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Snow Blowers
|
3914 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Tractors
|
3915 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment > Weed Trimmers
|
3916 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories
|
3917 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Chainsaw Accessories
|
3918 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Chainsaw Accessories > Chainsaw Bars
|
3919 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Chainsaw Accessories > Chainsaw Chains
|
3920 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Grass Edger Accessories
|
3921 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Hedge Trimmer Accessories
|
3922 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories
|
3923 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Brush Mower Attachments
|
3924 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Bags
|
3925 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Belts
|
3926 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Blades
|
3927 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Covers
|
3928 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Mulch Kits
|
3929 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Mulch Plugs & Plates
|
3930 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Pulleys & Idlers
|
3931 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Tire Tubes
|
3932 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Tires
|
3933 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Mower Wheels
|
3934 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Striping Kits
|
3935 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Lawn Mower Accessories > Lawn Sweepers
|
3936 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Leaf Blower Accessories
|
3937 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Leaf Blower Accessories > Leaf Blower Tubes
|
3938 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Multifunction Outdoor Power Equipment Attachments
|
3939 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Multifunction Outdoor Power Equipment Attachments > Grass Edger Attachments
|
3940 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Multifunction Outdoor Power Equipment Attachments > Ground & Leaf Blower Attachments
|
3941 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Multifunction Outdoor Power Equipment Attachments > Hedge Trimmer Attachments
|
3942 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Multifunction Outdoor Power Equipment Attachments > Pole Saw Attachments
|
3943 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Multifunction Outdoor Power Equipment Attachments > Tiller & Cultivator Attachments
|
3944 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Multifunction Outdoor Power Equipment Attachments > Weed Trimmer Attachments
|
3945 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Outdoor Power Equipment Batteries
|
3946 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Pressure Washer Accessories
|
3947 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Snow Blower Accessories
|
3948 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Tractor Parts & Accessories
|
3949 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Tractor Parts & Accessories > Tractor Tires
|
3950 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Tractor Parts & Accessories > Tractor Wheels
|
3951 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Weed Trimmer Accessories
|
3952 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Weed Trimmer Accessories > Weed Trimmer Blades & Spools
|
3953 |
+
Home & Garden > Lawn & Garden > Outdoor Power Equipment Accessories > Weed Trimmer Accessories > Weed Trimmer Spool Covers
|
3954 |
+
Home & Garden > Lawn & Garden > Snow Removal
|
3955 |
+
Home & Garden > Lawn & Garden > Snow Removal > Ice Scrapers & Snow Brushes
|
3956 |
+
Home & Garden > Lawn & Garden > Snow Removal > Snow Shovels
|
3957 |
+
Home & Garden > Lawn & Garden > Watering & Irrigation
|
3958 |
+
Home & Garden > Lawn & Garden > Watering & Irrigation > Garden Hose Fittings & Valves
|
3959 |
+
Home & Garden > Lawn & Garden > Watering & Irrigation > Garden Hose Spray Nozzles
|
3960 |
+
Home & Garden > Lawn & Garden > Watering & Irrigation > Garden Hoses
|
3961 |
+
Home & Garden > Lawn & Garden > Watering & Irrigation > Sprinkler Accessories
|
3962 |
+
Home & Garden > Lawn & Garden > Watering & Irrigation > Sprinkler Accessories > Sprinkler Controls
|
3963 |
+
Home & Garden > Lawn & Garden > Watering & Irrigation > Sprinkler Accessories > Sprinkler Valves
|
3964 |
+
Home & Garden > Lawn & Garden > Watering & Irrigation > Sprinklers & Sprinkler Heads
|
3965 |
+
Home & Garden > Lawn & Garden > Watering & Irrigation > Watering Can Accesssories
|
3966 |
+
Home & Garden > Lawn & Garden > Watering & Irrigation > Watering Cans
|
3967 |
+
Home & Garden > Lawn & Garden > Watering & Irrigation > Watering Globes & Spikes
|
3968 |
+
Home & Garden > Lighting
|
3969 |
+
Home & Garden > Lighting > Emergency Lighting
|
3970 |
+
Home & Garden > Lighting > Floating & Submersible Lights
|
3971 |
+
Home & Garden > Lighting > Flood & Spot Lights
|
3972 |
+
Home & Garden > Lighting > In-Ground Lights
|
3973 |
+
Home & Garden > Lighting > Lamps
|
3974 |
+
Home & Garden > Lighting > Landscape Pathway Lighting
|
3975 |
+
Home & Garden > Lighting > Light Bulbs
|
3976 |
+
Home & Garden > Lighting > Light Bulbs > Compact Fluorescent Lamps
|
3977 |
+
Home & Garden > Lighting > Light Bulbs > Fluorescent Tubes
|
3978 |
+
Home & Garden > Lighting > Light Bulbs > Incandescent Light Bulbs
|
3979 |
+
Home & Garden > Lighting > Light Bulbs > LED Light Bulbs
|
3980 |
+
Home & Garden > Lighting > Light Ropes & Strings
|
3981 |
+
Home & Garden > Lighting > Lighting Fixtures
|
3982 |
+
Home & Garden > Lighting > Lighting Fixtures > Cabinet Light Fixtures
|
3983 |
+
Home & Garden > Lighting > Lighting Fixtures > Ceiling Light Fixtures
|
3984 |
+
Home & Garden > Lighting > Lighting Fixtures > Chandeliers
|
3985 |
+
Home & Garden > Lighting > Lighting Fixtures > Wall Light Fixtures
|
3986 |
+
Home & Garden > Lighting > Night Lights & Ambient Lighting
|
3987 |
+
Home & Garden > Lighting > Picture Lights
|
3988 |
+
Home & Garden > Lighting > Tiki Torches & Oil Lamps
|
3989 |
+
Home & Garden > Lighting > Track Lighting
|
3990 |
+
Home & Garden > Lighting > Track Lighting > Track Lighting Accessories
|
3991 |
+
Home & Garden > Lighting > Track Lighting > Track Lighting Fixtures
|
3992 |
+
Home & Garden > Lighting > Track Lighting > Track Lighting Rails
|
3993 |
+
Home & Garden > Lighting Accessories
|
3994 |
+
Home & Garden > Lighting Accessories > Lamp Post Bases
|
3995 |
+
Home & Garden > Lighting Accessories > Lamp Post Mounts
|
3996 |
+
Home & Garden > Lighting Accessories > Lamp Shades
|
3997 |
+
Home & Garden > Lighting Accessories > Lighting Timers
|
3998 |
+
Home & Garden > Lighting Accessories > Oil Lamp Fuel
|
3999 |
+
Home & Garden > Linens & Bedding
|
4000 |
+
Home & Garden > Linens & Bedding > Bedding
|
4001 |
+
Home & Garden > Linens & Bedding > Bedding > Bed Canopies
|
4002 |
+
Home & Garden > Linens & Bedding > Bedding > Bed Sheets
|
4003 |
+
Home & Garden > Linens & Bedding > Bedding > Bedskirts
|
4004 |
+
Home & Garden > Linens & Bedding > Bedding > Blankets
|
4005 |
+
Home & Garden > Linens & Bedding > Bedding > Duvet Covers
|
4006 |
+
Home & Garden > Linens & Bedding > Bedding > Mattress Protectors
|
4007 |
+
Home & Garden > Linens & Bedding > Bedding > Mattress Protectors > Mattress Encasements
|
4008 |
+
Home & Garden > Linens & Bedding > Bedding > Mattress Protectors > Mattress Pads
|
4009 |
+
Home & Garden > Linens & Bedding > Bedding > Nap Mats
|
4010 |
+
Home & Garden > Linens & Bedding > Bedding > Pillowcases & Shams
|
4011 |
+
Home & Garden > Linens & Bedding > Bedding > Pillows
|
4012 |
+
Home & Garden > Linens & Bedding > Bedding > Quilts & Comforters
|
4013 |
+
Home & Garden > Linens & Bedding > Kitchen Linens Sets
|
4014 |
+
Home & Garden > Linens & Bedding > Table Linens
|
4015 |
+
Home & Garden > Linens & Bedding > Table Linens > Cloth Napkins
|
4016 |
+
Home & Garden > Linens & Bedding > Table Linens > Doilies
|
4017 |
+
Home & Garden > Linens & Bedding > Table Linens > Placemats
|
4018 |
+
Home & Garden > Linens & Bedding > Table Linens > Table Runners
|
4019 |
+
Home & Garden > Linens & Bedding > Table Linens > Table Skirts
|
4020 |
+
Home & Garden > Linens & Bedding > Table Linens > Tablecloths
|
4021 |
+
Home & Garden > Linens & Bedding > Towels
|
4022 |
+
Home & Garden > Linens & Bedding > Towels > Bath Towels & Washcloths
|
4023 |
+
Home & Garden > Linens & Bedding > Towels > Beach Towels
|
4024 |
+
Home & Garden > Linens & Bedding > Towels > Kitchen Towels
|
4025 |
+
Home & Garden > Parasols & Rain Umbrellas
|
4026 |
+
Home & Garden > Plants
|
4027 |
+
Home & Garden > Plants > Aquatic Plants
|
4028 |
+
Home & Garden > Plants > Flowers
|
4029 |
+
Home & Garden > Plants > Indoor & Outdoor Plants
|
4030 |
+
Home & Garden > Plants > Indoor & Outdoor Plants > Bushes & Shrubs
|
4031 |
+
Home & Garden > Plants > Indoor & Outdoor Plants > Landscaping & Garden Plants
|
4032 |
+
Home & Garden > Plants > Indoor & Outdoor Plants > Potted Houseplants
|
4033 |
+
Home & Garden > Plants > Plant & Herb Growing Kits
|
4034 |
+
Home & Garden > Plants > Seeds
|
4035 |
+
Home & Garden > Plants > Seeds > Plant & Flower Bulbs
|
4036 |
+
Home & Garden > Plants > Seeds > Seeds & Seed Tape
|
4037 |
+
Home & Garden > Plants > Trees
|
4038 |
+
Home & Garden > Pool & Spa
|
4039 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories
|
4040 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Diving Boards
|
4041 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool & Spa Chlorine Generators
|
4042 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool & Spa Filters
|
4043 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool & Spa Maintenance Kits
|
4044 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Brushes & Brooms
|
4045 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Cleaner Hoses
|
4046 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Cleaners & Chemicals
|
4047 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Cover Accessories
|
4048 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Covers & Ground Cloths
|
4049 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Deck Kits
|
4050 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Floats & Loungers
|
4051 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Heaters
|
4052 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Ladders, Steps & Ramps
|
4053 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Liners
|
4054 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Skimmers
|
4055 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Sweeps & Vacuums
|
4056 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Toys
|
4057 |
+
Home & Garden > Pool & Spa > Pool & Spa Accessories > Pool Water Slides
|
4058 |
+
Home & Garden > Pool & Spa > Sauna Accessories
|
4059 |
+
Home & Garden > Pool & Spa > Sauna Accessories > Sauna Buckets & Ladles
|
4060 |
+
Home & Garden > Pool & Spa > Sauna Accessories > Sauna Heaters
|
4061 |
+
Home & Garden > Pool & Spa > Sauna Accessories > Sauna Kits
|
4062 |
+
Home & Garden > Pool & Spa > Saunas
|
4063 |
+
Home & Garden > Pool & Spa > Spas
|
4064 |
+
Home & Garden > Pool & Spa > Swimming Pools
|
4065 |
+
Home & Garden > Smoking Accessories
|
4066 |
+
Home & Garden > Smoking Accessories > Ashtrays
|
4067 |
+
Home & Garden > Smoking Accessories > Cigar Cases
|
4068 |
+
Home & Garden > Smoking Accessories > Cigar Cutters & Punches
|
4069 |
+
Home & Garden > Smoking Accessories > Cigarette Cases
|
4070 |
+
Home & Garden > Smoking Accessories > Cigarette Holders
|
4071 |
+
Home & Garden > Smoking Accessories > Humidor Accessories
|
4072 |
+
Home & Garden > Smoking Accessories > Humidors
|
4073 |
+
Home & Garden > Umbrella Sleeves & Cases
|
4074 |
+
Home & Garden > Wood Stoves
|
4075 |
+
Luggage & Bags
|
4076 |
+
Luggage & Bags > Backpacks
|
4077 |
+
Luggage & Bags > Briefcases
|
4078 |
+
Luggage & Bags > Cosmetic & Toiletry Bags
|
4079 |
+
Luggage & Bags > Diaper Bags
|
4080 |
+
Luggage & Bags > Dry Boxes
|
4081 |
+
Luggage & Bags > Duffel Bags
|
4082 |
+
Luggage & Bags > Fanny Packs
|
4083 |
+
Luggage & Bags > Garment Bags
|
4084 |
+
Luggage & Bags > Luggage Accessories
|
4085 |
+
Luggage & Bags > Luggage Accessories > Dry Box Liners & Inserts
|
4086 |
+
Luggage & Bags > Luggage Accessories > Luggage Covers
|
4087 |
+
Luggage & Bags > Luggage Accessories > Luggage Racks & Stands
|
4088 |
+
Luggage & Bags > Luggage Accessories > Luggage Straps
|
4089 |
+
Luggage & Bags > Luggage Accessories > Luggage Tags
|
4090 |
+
Luggage & Bags > Luggage Accessories > Packing Organizers
|
4091 |
+
Luggage & Bags > Luggage Accessories > Travel Bottles & Containers
|
4092 |
+
Luggage & Bags > Luggage Accessories > Travel Pouches
|
4093 |
+
Luggage & Bags > Messenger Bags
|
4094 |
+
Luggage & Bags > Shopping Totes
|
4095 |
+
Luggage & Bags > Suitcases
|
4096 |
+
Luggage & Bags > Train Cases
|
4097 |
+
Mature
|
4098 |
+
Mature > Erotic
|
4099 |
+
Mature > Erotic > Erotic Books
|
4100 |
+
Mature > Erotic > Erotic Clothing
|
4101 |
+
Mature > Erotic > Erotic DVDs & Videos
|
4102 |
+
Mature > Erotic > Erotic Food & Edibles
|
4103 |
+
Mature > Erotic > Erotic Games
|
4104 |
+
Mature > Erotic > Erotic Magazines
|
4105 |
+
Mature > Erotic > Pole Dancing Kits
|
4106 |
+
Mature > Erotic > Sex Toys
|
4107 |
+
Mature > Weapons
|
4108 |
+
Mature > Weapons > Brass Knuckles
|
4109 |
+
Mature > Weapons > Clubs & Batons
|
4110 |
+
Mature > Weapons > Combat Knives
|
4111 |
+
Mature > Weapons > Gun Care & Accessories
|
4112 |
+
Mature > Weapons > Gun Care & Accessories > Ammunition
|
4113 |
+
Mature > Weapons > Gun Care & Accessories > Ammunition Cases & Holders
|
4114 |
+
Mature > Weapons > Gun Care & Accessories > Gun Cases & Range Bags
|
4115 |
+
Mature > Weapons > Gun Care & Accessories > Gun Cleaning
|
4116 |
+
Mature > Weapons > Gun Care & Accessories > Gun Cleaning > Gun Cleaning Cloths & Swabs
|
4117 |
+
Mature > Weapons > Gun Care & Accessories > Gun Cleaning > Gun Cleaning Patches
|
4118 |
+
Mature > Weapons > Gun Care & Accessories > Gun Cleaning > Gun Cleaning Solvents
|
4119 |
+
Mature > Weapons > Gun Care & Accessories > Gun Grips
|
4120 |
+
Mature > Weapons > Gun Care & Accessories > Gun Holsters
|
4121 |
+
Mature > Weapons > Gun Care & Accessories > Gun Lights
|
4122 |
+
Mature > Weapons > Gun Care & Accessories > Gun Rails
|
4123 |
+
Mature > Weapons > Gun Care & Accessories > Gun Slings
|
4124 |
+
Mature > Weapons > Gun Care & Accessories > Reloading Supplies & Equipment
|
4125 |
+
Mature > Weapons > Gun Care & Accessories > Reloading Supplies & Equipment > Ammunition Reloading Presses
|
4126 |
+
Mature > Weapons > Guns
|
4127 |
+
Mature > Weapons > Mace & Pepper Spray
|
4128 |
+
Mature > Weapons > Nunchucks
|
4129 |
+
Mature > Weapons > Spears
|
4130 |
+
Mature > Weapons > Staff & Stick Weapons
|
4131 |
+
Mature > Weapons > Stun Guns & Tasers
|
4132 |
+
Mature > Weapons > Swords
|
4133 |
+
Mature > Weapons > Throwing Stars
|
4134 |
+
Mature > Weapons > Whips
|
4135 |
+
Media
|
4136 |
+
Media > Books
|
4137 |
+
Media > Books > Audiobooks
|
4138 |
+
Media > Books > E-books
|
4139 |
+
Media > Books > Print Books
|
4140 |
+
Media > Carpentry & Woodworking Project Plans
|
4141 |
+
Media > DVDs & Videos
|
4142 |
+
Media > DVDs & Videos > Film & Television DVDs
|
4143 |
+
Media > DVDs & Videos > Film & Television Digital Downloads
|
4144 |
+
Media > DVDs & Videos > Film & Television VHS Tapes
|
4145 |
+
Media > Magazines & Newspapers
|
4146 |
+
Media > Magazines & Newspapers > Magazines
|
4147 |
+
Media > Magazines & Newspapers > Newspapers
|
4148 |
+
Media > Music & Sound Recordings
|
4149 |
+
Media > Music & Sound Recordings > Digital Music Downloads
|
4150 |
+
Media > Music & Sound Recordings > Music CDs
|
4151 |
+
Media > Music & Sound Recordings > Music Cassette Tapes
|
4152 |
+
Media > Music & Sound Recordings > Records & LPs
|
4153 |
+
Media > Music & Sound Recordings > Spoken Word & Field Recordings
|
4154 |
+
Media > Product Manuals
|
4155 |
+
Media > Product Manuals > Camera & Optics Manuals
|
4156 |
+
Media > Product Manuals > Electronics Manuals
|
4157 |
+
Media > Product Manuals > Exercise & Fitness Equipment Manuals
|
4158 |
+
Media > Product Manuals > Household Appliance Manuals
|
4159 |
+
Media > Product Manuals > Kitchen Appliance Manuals
|
4160 |
+
Media > Product Manuals > Model & Toys Manuals
|
4161 |
+
Media > Product Manuals > Office Supply Manuals
|
4162 |
+
Media > Product Manuals > Power Tool & Equipment Manuals
|
4163 |
+
Media > Product Manuals > Vehicle Service Manuals
|
4164 |
+
Media > Sheet Music
|
4165 |
+
Office Supplies
|
4166 |
+
Office Supplies > Book Accessories
|
4167 |
+
Office Supplies > Book Accessories > Book Covers
|
4168 |
+
Office Supplies > Book Accessories > Book Lights
|
4169 |
+
Office Supplies > Book Accessories > Book Stands & Rests
|
4170 |
+
Office Supplies > Book Accessories > Bookmarks
|
4171 |
+
Office Supplies > Desk Pads & Blotters
|
4172 |
+
Office Supplies > Filing & Organization
|
4173 |
+
Office Supplies > Filing & Organization > Address Books
|
4174 |
+
Office Supplies > Filing & Organization > Binding Supplies
|
4175 |
+
Office Supplies > Filing & Organization > Binding Supplies > Binder Accessories
|
4176 |
+
Office Supplies > Filing & Organization > Binding Supplies > Binder Accessories > Binder Rings
|
4177 |
+
Office Supplies > Filing & Organization > Binding Supplies > Binder Accessories > Index Dividers
|
4178 |
+
Office Supplies > Filing & Organization > Binding Supplies > Binder Accessories > Sheet Protectors
|
4179 |
+
Office Supplies > Filing & Organization > Binding Supplies > Binders
|
4180 |
+
Office Supplies > Filing & Organization > Binding Supplies > Binding Combs & Spines
|
4181 |
+
Office Supplies > Filing & Organization > Binding Supplies > Binding Machines
|
4182 |
+
Office Supplies > Filing & Organization > Business Card Books
|
4183 |
+
Office Supplies > Filing & Organization > Business Card Stands
|
4184 |
+
Office Supplies > Filing & Organization > CD/DVD Cases & Organizers
|
4185 |
+
Office Supplies > Filing & Organization > Calendars, Organizers & Planners
|
4186 |
+
Office Supplies > Filing & Organization > Card Files
|
4187 |
+
Office Supplies > Filing & Organization > Card Sleeves
|
4188 |
+
Office Supplies > Filing & Organization > Cash Boxes
|
4189 |
+
Office Supplies > Filing & Organization > Desk Organizers
|
4190 |
+
Office Supplies > Filing & Organization > File Boxes
|
4191 |
+
Office Supplies > Filing & Organization > File Folders
|
4192 |
+
Office Supplies > Filing & Organization > Folders & Report Covers
|
4193 |
+
Office Supplies > Filing & Organization > Folders & Report Covers > Pocket Folders
|
4194 |
+
Office Supplies > Filing & Organization > Folders & Report Covers > Report Covers
|
4195 |
+
Office Supplies > Filing & Organization > Greeting Card Organizers
|
4196 |
+
Office Supplies > Filing & Organization > Mail Sorters
|
4197 |
+
Office Supplies > Filing & Organization > Pen & Pencil Cases
|
4198 |
+
Office Supplies > Filing & Organization > Portfolios & Padfolios
|
4199 |
+
Office Supplies > Filing & Organization > Portfolios & Padfolios > Padfolios
|
4200 |
+
Office Supplies > Filing & Organization > Portfolios & Padfolios > Portfolios
|
4201 |
+
Office Supplies > Filing & Organization > Recipe Card Boxes
|
4202 |
+
Office Supplies > General Office Supplies
|
4203 |
+
Office Supplies > General Office Supplies > Brass Fasteners
|
4204 |
+
Office Supplies > General Office Supplies > Correction Fluids, Pens & Tapes
|
4205 |
+
Office Supplies > General Office Supplies > Correction Fluids, Pens & Tapes > Correction Fluids
|
4206 |
+
Office Supplies > General Office Supplies > Correction Fluids, Pens & Tapes > Correction Pens
|
4207 |
+
Office Supplies > General Office Supplies > Correction Fluids, Pens & Tapes > Correction Tapes
|
4208 |
+
Office Supplies > General Office Supplies > Erasers
|
4209 |
+
Office Supplies > General Office Supplies > Labels & Tags
|
4210 |
+
Office Supplies > General Office Supplies > Labels & Tags > Address Labels
|
4211 |
+
Office Supplies > General Office Supplies > Labels & Tags > Folder Tabs
|
4212 |
+
Office Supplies > General Office Supplies > Labels & Tags > Label Clips
|
4213 |
+
Office Supplies > General Office Supplies > Labels & Tags > Label Tapes & Refill Rolls
|
4214 |
+
Office Supplies > General Office Supplies > Labels & Tags > Shipping Labels
|
4215 |
+
Office Supplies > General Office Supplies > Labels & Tags > Shipping Tags
|
4216 |
+
Office Supplies > General Office Supplies > Laminating Film, Pouches & Sheets
|
4217 |
+
Office Supplies > General Office Supplies > Mounting Putty
|
4218 |
+
Office Supplies > General Office Supplies > Office Tape
|
4219 |
+
Office Supplies > General Office Supplies > Paper Clips & Clamps
|
4220 |
+
Office Supplies > General Office Supplies > Paper Clips & Clamps > Binder Clips
|
4221 |
+
Office Supplies > General Office Supplies > Paper Clips & Clamps > Paper Clips
|
4222 |
+
Office Supplies > General Office Supplies > Paper Products
|
4223 |
+
Office Supplies > General Office Supplies > Paper Products > Binder Paper
|
4224 |
+
Office Supplies > General Office Supplies > Paper Products > Blank ID Cards
|
4225 |
+
Office Supplies > General Office Supplies > Paper Products > Business Cards
|
4226 |
+
Office Supplies > General Office Supplies > Paper Products > Business Forms & Receipts
|
4227 |
+
Office Supplies > General Office Supplies > Paper Products > Checks
|
4228 |
+
Office Supplies > General Office Supplies > Paper Products > Cover Paper
|
4229 |
+
Office Supplies > General Office Supplies > Paper Products > Envelopes
|
4230 |
+
Office Supplies > General Office Supplies > Paper Products > Index Cards
|
4231 |
+
Office Supplies > General Office Supplies > Paper Products > Notebooks & Notepads
|
4232 |
+
Office Supplies > General Office Supplies > Paper Products > Post Cards
|
4233 |
+
Office Supplies > General Office Supplies > Paper Products > Printer & Copier Paper
|
4234 |
+
Office Supplies > General Office Supplies > Paper Products > Receipt & Adding Machine Paper Rolls
|
4235 |
+
Office Supplies > General Office Supplies > Paper Products > Stationery
|
4236 |
+
Office Supplies > General Office Supplies > Paper Products > Sticky Notes
|
4237 |
+
Office Supplies > General Office Supplies > Rubber Bands
|
4238 |
+
Office Supplies > General Office Supplies > Staples
|
4239 |
+
Office Supplies > General Office Supplies > Tacks & Pushpins
|
4240 |
+
Office Supplies > Impulse Sealers
|
4241 |
+
Office Supplies > Lap Desks
|
4242 |
+
Office Supplies > Name Plates
|
4243 |
+
Office Supplies > Office & Chair Mats
|
4244 |
+
Office Supplies > Office & Chair Mats > Anti-Fatigue Mats
|
4245 |
+
Office Supplies > Office & Chair Mats > Chair Mats
|
4246 |
+
Office Supplies > Office & Chair Mats > Office Mats
|
4247 |
+
Office Supplies > Office Carts
|
4248 |
+
Office Supplies > Office Carts > AV Carts
|
4249 |
+
Office Supplies > Office Carts > Book Carts
|
4250 |
+
Office Supplies > Office Carts > File Carts
|
4251 |
+
Office Supplies > Office Carts > Mail Carts
|
4252 |
+
Office Supplies > Office Carts > Utility Carts
|
4253 |
+
Office Supplies > Office Equipment
|
4254 |
+
Office Supplies > Office Equipment > Calculator Accessories
|
4255 |
+
Office Supplies > Office Equipment > Calculators
|
4256 |
+
Office Supplies > Office Equipment > Calculators > Basic Calculators
|
4257 |
+
Office Supplies > Office Equipment > Calculators > Construction Calculators
|
4258 |
+
Office Supplies > Office Equipment > Calculators > Financial Calculators
|
4259 |
+
Office Supplies > Office Equipment > Calculators > Graphing Calculators
|
4260 |
+
Office Supplies > Office Equipment > Calculators > Scientific Calculators
|
4261 |
+
Office Supplies > Office Equipment > Electronic Dictionaries & Translators
|
4262 |
+
Office Supplies > Office Equipment > Label Makers
|
4263 |
+
Office Supplies > Office Equipment > Laminators
|
4264 |
+
Office Supplies > Office Equipment > Office Shredders
|
4265 |
+
Office Supplies > Office Equipment > Postage Meters
|
4266 |
+
Office Supplies > Office Equipment > Time & Attendance Clocks
|
4267 |
+
Office Supplies > Office Equipment > Transcribers & Dictation Systems
|
4268 |
+
Office Supplies > Office Equipment > Typewriters
|
4269 |
+
Office Supplies > Office Instruments
|
4270 |
+
Office Supplies > Office Instruments > Call Bells
|
4271 |
+
Office Supplies > Office Instruments > Clipboards
|
4272 |
+
Office Supplies > Office Instruments > Letter Openers
|
4273 |
+
Office Supplies > Office Instruments > Magnifiers
|
4274 |
+
Office Supplies > Office Instruments > Office Rubber Stamps
|
4275 |
+
Office Supplies > Office Instruments > Pencil Sharpeners
|
4276 |
+
Office Supplies > Office Instruments > Staple Removers
|
4277 |
+
Office Supplies > Office Instruments > Staplers
|
4278 |
+
Office Supplies > Office Instruments > Tape Dispensers
|
4279 |
+
Office Supplies > Office Instruments > Writing & Drawing Instrument Accessories
|
4280 |
+
Office Supplies > Office Instruments > Writing & Drawing Instrument Accessories > Marker & Highlighter Ink Refills
|
4281 |
+
Office Supplies > Office Instruments > Writing & Drawing Instrument Accessories > Marker & Highlighter Ink Refills > Highlighter Refills
|
4282 |
+
Office Supplies > Office Instruments > Writing & Drawing Instrument Accessories > Marker & Highlighter Ink Refills > Marker Refills
|
4283 |
+
Office Supplies > Office Instruments > Writing & Drawing Instrument Accessories > Pen Ink & Refills
|
4284 |
+
Office Supplies > Office Instruments > Writing & Drawing Instrument Accessories > Pencil Lead & Refills
|
4285 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments
|
4286 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Art Charcoals
|
4287 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Chalk
|
4288 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Crayons
|
4289 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Markers & Highlighters
|
4290 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Markers & Highlighters > Highlighters
|
4291 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Markers & Highlighters > Markers
|
4292 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Multifunction Writing Instruments
|
4293 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Pastels
|
4294 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils
|
4295 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils > Pen & Pencil Sets
|
4296 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils > Pencils
|
4297 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils > Pencils > Art Pencils
|
4298 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils > Pencils > Writing Pencils
|
4299 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils > Pencils > Writing Pencils > Mechanical Pencils
|
4300 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils > Pencils > Writing Pencils > Wooden Pencils
|
4301 |
+
Office Supplies > Office Instruments > Writing & Drawing Instruments > Pens & Pencils > Pens
|
4302 |
+
Office Supplies > Paper Handling
|
4303 |
+
Office Supplies > Paper Handling > Fingertip Grips
|
4304 |
+
Office Supplies > Paper Handling > Hole Punches
|
4305 |
+
Office Supplies > Paper Handling > Paper Folding Machines
|
4306 |
+
Office Supplies > Paper Handling > Paper Joggers
|
4307 |
+
Office Supplies > Paper Handling > Paperweights
|
4308 |
+
Office Supplies > Paper Handling > Pencil Boards
|
4309 |
+
Office Supplies > Presentation Supplies
|
4310 |
+
Office Supplies > Presentation Supplies > Chalkboards
|
4311 |
+
Office Supplies > Presentation Supplies > Display Boards
|
4312 |
+
Office Supplies > Presentation Supplies > Display Boards > Bulletin Board Accessories
|
4313 |
+
Office Supplies > Presentation Supplies > Display Boards > Bulletin Board Accessories > Bulletin Board Trim
|
4314 |
+
Office Supplies > Presentation Supplies > Display Boards > Bulletin Board Accessories > Bulletin Board Trim Sets
|
4315 |
+
Office Supplies > Presentation Supplies > Display Boards > Bulletin Boards
|
4316 |
+
Office Supplies > Presentation Supplies > Display Boards > Foam Boards
|
4317 |
+
Office Supplies > Presentation Supplies > Display Boards > Mounting Boards
|
4318 |
+
Office Supplies > Presentation Supplies > Display Boards > Poster Boards
|
4319 |
+
Office Supplies > Presentation Supplies > Document Cameras
|
4320 |
+
Office Supplies > Presentation Supplies > Dry-Erase Boards
|
4321 |
+
Office Supplies > Presentation Supplies > Easel Pads
|
4322 |
+
Office Supplies > Presentation Supplies > Easels
|
4323 |
+
Office Supplies > Presentation Supplies > Laser Pointers
|
4324 |
+
Office Supplies > Presentation Supplies > Lecterns
|
4325 |
+
Office Supplies > Presentation Supplies > Transparencies
|
4326 |
+
Office Supplies > Presentation Supplies > Wireless Presenters
|
4327 |
+
Office Supplies > Shipping Supplies
|
4328 |
+
Office Supplies > Shipping Supplies > Moving & Shipping Boxes
|
4329 |
+
Office Supplies > Shipping Supplies > Packing Materials
|
4330 |
+
Office Supplies > Shipping Supplies > Packing Tape
|
4331 |
+
Religious & Ceremonial
|
4332 |
+
Religious & Ceremonial > Memorial Ceremony Supplies
|
4333 |
+
Religious & Ceremonial > Memorial Ceremony Supplies > Memorial Urns
|
4334 |
+
Religious & Ceremonial > Religious Items
|
4335 |
+
Religious & Ceremonial > Religious Items > Prayer Beads
|
4336 |
+
Religious & Ceremonial > Religious Items > Prayer Cards
|
4337 |
+
Religious & Ceremonial > Religious Items > Religious Altars
|
4338 |
+
Religious & Ceremonial > Religious Items > Religious Veils
|
4339 |
+
Religious & Ceremonial > Religious Items > Tarot Cards
|
4340 |
+
Religious & Ceremonial > Wedding Ceremony Supplies
|
4341 |
+
Religious & Ceremonial > Wedding Ceremony Supplies > Aisle Runners
|
4342 |
+
Religious & Ceremonial > Wedding Ceremony Supplies > Flower Girl Baskets
|
4343 |
+
Religious & Ceremonial > Wedding Ceremony Supplies > Ring Pillows & Holders
|
4344 |
+
Software
|
4345 |
+
Software > Computer Software
|
4346 |
+
Software > Computer Software > Antivirus & Security Software
|
4347 |
+
Software > Computer Software > Business & Productivity Software
|
4348 |
+
Software > Computer Software > Compilers & Programming Tools
|
4349 |
+
Software > Computer Software > Computer Utilities & Maintenance Software
|
4350 |
+
Software > Computer Software > Dictionary & Translation Software
|
4351 |
+
Software > Computer Software > Educational Software
|
4352 |
+
Software > Computer Software > Financial, Tax & Accounting Software
|
4353 |
+
Software > Computer Software > GPS Map Data & Software
|
4354 |
+
Software > Computer Software > Handheld & PDA Software
|
4355 |
+
Software > Computer Software > Multimedia & Design Software
|
4356 |
+
Software > Computer Software > Multimedia & Design Software > 3D Modeling Software
|
4357 |
+
Software > Computer Software > Multimedia & Design Software > Animation Editing Software
|
4358 |
+
Software > Computer Software > Multimedia & Design Software > Graphic Design & Illustration Software
|
4359 |
+
Software > Computer Software > Multimedia & Design Software > Home & Interior Design Software
|
4360 |
+
Software > Computer Software > Multimedia & Design Software > Home Publishing Software
|
4361 |
+
Software > Computer Software > Multimedia & Design Software > Media Viewing Software
|
4362 |
+
Software > Computer Software > Multimedia & Design Software > Music Composition Software
|
4363 |
+
Software > Computer Software > Multimedia & Design Software > Sound Editing Software
|
4364 |
+
Software > Computer Software > Multimedia & Design Software > Video Editing Software
|
4365 |
+
Software > Computer Software > Multimedia & Design Software > Web Design Software
|
4366 |
+
Software > Computer Software > Network Software
|
4367 |
+
Software > Computer Software > Office Application Software
|
4368 |
+
Software > Computer Software > Operating Systems
|
4369 |
+
Software > Computer Software > Restore Disks
|
4370 |
+
Software > Digital Goods & Currency
|
4371 |
+
Software > Digital Goods & Currency > Computer Icons
|
4372 |
+
Software > Digital Goods & Currency > Desktop Wallpaper
|
4373 |
+
Software > Digital Goods & Currency > Digital Artwork
|
4374 |
+
Software > Digital Goods & Currency > Document Templates
|
4375 |
+
Software > Digital Goods & Currency > Fonts
|
4376 |
+
Software > Digital Goods & Currency > Stock Photographs & Video Footage
|
4377 |
+
Software > Digital Goods & Currency > Virtual Currency
|
4378 |
+
Software > Video Game Software
|
4379 |
+
Sporting Goods
|
4380 |
+
Sporting Goods > Athletics
|
4381 |
+
Sporting Goods > Athletics > Baseball & Softball
|
4382 |
+
Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Bases & Plates
|
4383 |
+
Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Batting Gloves
|
4384 |
+
Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Gloves & Mitts
|
4385 |
+
Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Pitching Mats
|
4386 |
+
Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Pitching Mounds
|
4387 |
+
Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Protective Gear
|
4388 |
+
Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Protective Gear > Baseball & Softball Batting Helmets
|
4389 |
+
Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Protective Gear > Baseball & Softball Chest Protectors
|
4390 |
+
Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Protective Gear > Baseball & Softball Leg Guards
|
4391 |
+
Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Protective Gear > Catchers Equipment Sets
|
4392 |
+
Sporting Goods > Athletics > Baseball & Softball > Baseball & Softball Protective Gear > Catchers Helmets & Masks
|
4393 |
+
Sporting Goods > Athletics > Baseball & Softball > Baseball Bats
|
4394 |
+
Sporting Goods > Athletics > Baseball & Softball > Baseballs
|
4395 |
+
Sporting Goods > Athletics > Baseball & Softball > Pitching Machines
|
4396 |
+
Sporting Goods > Athletics > Baseball & Softball > Softball Bats
|
4397 |
+
Sporting Goods > Athletics > Baseball & Softball > Softballs
|
4398 |
+
Sporting Goods > Athletics > Basketball
|
4399 |
+
Sporting Goods > Athletics > Basketball > Basketball Hoop Parts & Accessories
|
4400 |
+
Sporting Goods > Athletics > Basketball > Basketball Hoop Parts & Accessories > Basketball Backboards
|
4401 |
+
Sporting Goods > Athletics > Basketball > Basketball Hoop Parts & Accessories > Basketball Hoop Padding
|
4402 |
+
Sporting Goods > Athletics > Basketball > Basketball Hoop Parts & Accessories > Basketball Hoop Posts
|
4403 |
+
Sporting Goods > Athletics > Basketball > Basketball Hoop Parts & Accessories > Basketball Nets
|
4404 |
+
Sporting Goods > Athletics > Basketball > Basketball Hoop Parts & Accessories > Basketball Rims
|
4405 |
+
Sporting Goods > Athletics > Basketball > Basketball Hoops
|
4406 |
+
Sporting Goods > Athletics > Basketball > Basketball Training Aids
|
4407 |
+
Sporting Goods > Athletics > Basketball > Basketballs
|
4408 |
+
Sporting Goods > Athletics > Boxing & Martial Arts
|
4409 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Protective Gear
|
4410 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Protective Gear > Boxing & MMA Hand Wraps
|
4411 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Protective Gear > Boxing & Martial Arts Arm Guards
|
4412 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Protective Gear > Boxing & Martial Arts Body Protectors
|
4413 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Protective Gear > Boxing & Martial Arts Headgear
|
4414 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Protective Gear > Boxing Gloves & Mitts
|
4415 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Protective Gear > MMA Shin Guards
|
4416 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Training Equipment
|
4417 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Training Equipment > Boxing & MMA Punch Mitts
|
4418 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Training Equipment > Grappling Dummies
|
4419 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Training Equipment > Punching & Training Bag Accessories
|
4420 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Training Equipment > Punching & Training Bags
|
4421 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing & Martial Arts Training Equipment > Strike Shields
|
4422 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing Ring Parts
|
4423 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Boxing Rings
|
4424 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Martial Arts Belts
|
4425 |
+
Sporting Goods > Athletics > Boxing & Martial Arts > Martial Arts Weapons
|
4426 |
+
Sporting Goods > Athletics > Broomball Equipment
|
4427 |
+
Sporting Goods > Athletics > Cheerleading
|
4428 |
+
Sporting Goods > Athletics > Cheerleading > Cheerleading Pom Poms
|
4429 |
+
Sporting Goods > Athletics > Coaching & Officiating
|
4430 |
+
Sporting Goods > Athletics > Coaching & Officiating > Captains Armbands
|
4431 |
+
Sporting Goods > Athletics > Coaching & Officiating > Field & Court Boundary Markers
|
4432 |
+
Sporting Goods > Athletics > Coaching & Officiating > Flip Coins & Discs
|
4433 |
+
Sporting Goods > Athletics > Coaching & Officiating > Linesman Flags
|
4434 |
+
Sporting Goods > Athletics > Coaching & Officiating > Penalty Cards & Flags
|
4435 |
+
Sporting Goods > Athletics > Coaching & Officiating > Pitch Counters
|
4436 |
+
Sporting Goods > Athletics > Coaching & Officiating > Referee Stands & Chairs
|
4437 |
+
Sporting Goods > Athletics > Coaching & Officiating > Referee Wallets
|
4438 |
+
Sporting Goods > Athletics > Coaching & Officiating > Scoreboards
|
4439 |
+
Sporting Goods > Athletics > Coaching & Officiating > Sport & Safety Whistles
|
4440 |
+
Sporting Goods > Athletics > Coaching & Officiating > Umpire Indicators
|
4441 |
+
Sporting Goods > Athletics > Cricket
|
4442 |
+
Sporting Goods > Athletics > Cricket > Cricket Balls
|
4443 |
+
Sporting Goods > Athletics > Cricket > Cricket Bat Accessories
|
4444 |
+
Sporting Goods > Athletics > Cricket > Cricket Bat Accessories > Cricket Bat Grips
|
4445 |
+
Sporting Goods > Athletics > Cricket > Cricket Bats
|
4446 |
+
Sporting Goods > Athletics > Cricket > Cricket Equipment Sets
|
4447 |
+
Sporting Goods > Athletics > Cricket > Cricket Protective Gear
|
4448 |
+
Sporting Goods > Athletics > Cricket > Cricket Protective Gear > Cricket Gloves
|
4449 |
+
Sporting Goods > Athletics > Cricket > Cricket Protective Gear > Cricket Helmets
|
4450 |
+
Sporting Goods > Athletics > Cricket > Cricket Protective Gear > Cricket Leg Guards
|
4451 |
+
Sporting Goods > Athletics > Cricket > Cricket Stumps
|
4452 |
+
Sporting Goods > Athletics > Dancing
|
4453 |
+
Sporting Goods > Athletics > Dancing > Ballet Barres
|
4454 |
+
Sporting Goods > Athletics > Fencing
|
4455 |
+
Sporting Goods > Athletics > Fencing > Fencing Protective Gear
|
4456 |
+
Sporting Goods > Athletics > Fencing > Fencing Protective Gear > Fencing Gloves & Cuffs
|
4457 |
+
Sporting Goods > Athletics > Fencing > Fencing Protective Gear > Fencing Jackets & Lamés
|
4458 |
+
Sporting Goods > Athletics > Fencing > Fencing Protective Gear > Fencing Masks
|
4459 |
+
Sporting Goods > Athletics > Fencing > Fencing Weapons
|
4460 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse
|
4461 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey & Lacrosse Protective Gear
|
4462 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey & Lacrosse Protective Gear > Field Hockey & Lacrosse Gloves
|
4463 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey & Lacrosse Protective Gear > Field Hockey & Lacrosse Helmets
|
4464 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey & Lacrosse Protective Gear > Field Hockey & Lacrosse Masks & Goggles
|
4465 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey & Lacrosse Protective Gear > Field Hockey & Lacrosse Pads
|
4466 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey Balls
|
4467 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey Goals
|
4468 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Field Hockey Sticks
|
4469 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Balls
|
4470 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Equipment Sets
|
4471 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Goals
|
4472 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Stick Parts
|
4473 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Stick Parts > Lacrosse Mesh & String
|
4474 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Stick Parts > Lacrosse Stick Heads
|
4475 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Stick Parts > Lacrosse Stick Shafts
|
4476 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Sticks
|
4477 |
+
Sporting Goods > Athletics > Field Hockey & Lacrosse > Lacrosse Training Aids
|
4478 |
+
Sporting Goods > Athletics > Figure Skating & Hockey
|
4479 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Balls & Pucks
|
4480 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Goals
|
4481 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear
|
4482 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Elbow Pads
|
4483 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Gloves
|
4484 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Goalie Equipment Sets
|
4485 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Helmets
|
4486 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Pants
|
4487 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Shin Guards & Leg Pads
|
4488 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Shoulder Pads & Chest Protectors
|
4489 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Protective Gear > Hockey Suspenders & Belts
|
4490 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Sledges
|
4491 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Stick Care
|
4492 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Stick Parts
|
4493 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Stick Parts > Hockey Stick Blades
|
4494 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Stick Parts > Hockey Stick Shafts
|
4495 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Hockey Sticks
|
4496 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Ice Skate Parts & Accessories
|
4497 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Ice Skate Parts & Accessories > Figure Skate Boots
|
4498 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Ice Skate Parts & Accessories > Ice Skate Blades
|
4499 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Ice Skate Parts & Accessories > Ice Skate Sharpeners
|
4500 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Ice Skate Parts & Accessories > Skate Blade Guards
|
4501 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Ice Skate Parts & Accessories > Skate Lace Tighteners
|
4502 |
+
Sporting Goods > Athletics > Figure Skating & Hockey > Ice Skates
|
4503 |
+
Sporting Goods > Athletics > Football
|
4504 |
+
Sporting Goods > Athletics > Football > Football Gloves
|
4505 |
+
Sporting Goods > Athletics > Football > Football Goal Posts
|
4506 |
+
Sporting Goods > Athletics > Football > Football Kicking Tees & Holders
|
4507 |
+
Sporting Goods > Athletics > Football > Football Protective Gear
|
4508 |
+
Sporting Goods > Athletics > Football > Football Protective Gear > Football Girdles
|
4509 |
+
Sporting Goods > Athletics > Football > Football Protective Gear > Football Helmet Accessories
|
4510 |
+
Sporting Goods > Athletics > Football > Football Protective Gear > Football Helmet Accessories > Football Chin Straps
|
4511 |
+
Sporting Goods > Athletics > Football > Football Protective Gear > Football Helmet Accessories > Football Face Masks
|
4512 |
+
Sporting Goods > Athletics > Football > Football Protective Gear > Football Helmet Accessories > Football Helmet Padding
|
4513 |
+
Sporting Goods > Athletics > Football > Football Protective Gear > Football Helmet Accessories > Football Helmet Visors
|
4514 |
+
Sporting Goods > Athletics > Football > Football Protective Gear > Football Helmets
|
4515 |
+
Sporting Goods > Athletics > Football > Football Protective Gear > Football Neck Rolls
|
4516 |
+
Sporting Goods > Athletics > Football > Football Protective Gear > Football Rib Protection Shirts & Vests
|
4517 |
+
Sporting Goods > Athletics > Football > Football Protective Gear > Football Shoulder Pads
|
4518 |
+
Sporting Goods > Athletics > Football > Football Training Equipment
|
4519 |
+
Sporting Goods > Athletics > Football > Football Training Equipment > Football Dummies & Sleds
|
4520 |
+
Sporting Goods > Athletics > Football > Footballs
|
4521 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment
|
4522 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Altitude Training Masks
|
4523 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Athletic Cups
|
4524 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Ball Carrying Bags & Carts
|
4525 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Ball Pump Accessories
|
4526 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Ball Pump Accessories > Ball Pump Needles
|
4527 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Ball Pumps
|
4528 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Exercise & Gym Mat Storage Racks & Carts
|
4529 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Grip Spray & Chalk
|
4530 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Gym Mats
|
4531 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Practice Nets & Screens
|
4532 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Speed & Agility Ladders & Hurdles
|
4533 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Sports & Agility Cones
|
4534 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Sports Megaphones
|
4535 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Sports Mouthguards
|
4536 |
+
Sporting Goods > Athletics > General Purpose Athletic Equipment > Stadium Seats & Cushions
|
4537 |
+
Sporting Goods > Athletics > Gymnastics
|
4538 |
+
Sporting Goods > Athletics > Gymnastics > Gymnastics Bars & Balance Beams
|
4539 |
+
Sporting Goods > Athletics > Gymnastics > Gymnastics Protective Gear
|
4540 |
+
Sporting Goods > Athletics > Gymnastics > Gymnastics Protective Gear > Gymnastics Grips
|
4541 |
+
Sporting Goods > Athletics > Gymnastics > Gymnastics Rings
|
4542 |
+
Sporting Goods > Athletics > Gymnastics > Gymnastics Springboards
|
4543 |
+
Sporting Goods > Athletics > Gymnastics > Pommel Horses
|
4544 |
+
Sporting Goods > Athletics > Gymnastics > Vaulting Horses
|
4545 |
+
Sporting Goods > Athletics > Racquetball & Squash
|
4546 |
+
Sporting Goods > Athletics > Racquetball & Squash > Racquetball & Squash Balls
|
4547 |
+
Sporting Goods > Athletics > Racquetball & Squash > Racquetball & Squash Eyewear
|
4548 |
+
Sporting Goods > Athletics > Racquetball & Squash > Racquetball & Squash Gloves
|
4549 |
+
Sporting Goods > Athletics > Racquetball & Squash > Racquetball Racquets
|
4550 |
+
Sporting Goods > Athletics > Racquetball & Squash > Squash Racquets
|
4551 |
+
Sporting Goods > Athletics > Rounders
|
4552 |
+
Sporting Goods > Athletics > Rounders > Rounders Bats
|
4553 |
+
Sporting Goods > Athletics > Rounders > Rounders Gloves
|
4554 |
+
Sporting Goods > Athletics > Rugby
|
4555 |
+
Sporting Goods > Athletics > Rugby > Rugby Balls
|
4556 |
+
Sporting Goods > Athletics > Rugby > Rugby Gloves
|
4557 |
+
Sporting Goods > Athletics > Rugby > Rugby Posts
|
4558 |
+
Sporting Goods > Athletics > Rugby > Rugby Protective Gear
|
4559 |
+
Sporting Goods > Athletics > Rugby > Rugby Protective Gear > Rugby Headgear
|
4560 |
+
Sporting Goods > Athletics > Rugby > Rugby Training Aids
|
4561 |
+
Sporting Goods > Athletics > Soccer
|
4562 |
+
Sporting Goods > Athletics > Soccer > Soccer Balls
|
4563 |
+
Sporting Goods > Athletics > Soccer > Soccer Corner Flags
|
4564 |
+
Sporting Goods > Athletics > Soccer > Soccer Gloves
|
4565 |
+
Sporting Goods > Athletics > Soccer > Soccer Goal Accessories
|
4566 |
+
Sporting Goods > Athletics > Soccer > Soccer Goals
|
4567 |
+
Sporting Goods > Athletics > Soccer > Soccer Protective Gear
|
4568 |
+
Sporting Goods > Athletics > Soccer > Soccer Protective Gear > Soccer Shin Guards
|
4569 |
+
Sporting Goods > Athletics > Team Handball
|
4570 |
+
Sporting Goods > Athletics > Team Handball > Handballs
|
4571 |
+
Sporting Goods > Athletics > Tennis
|
4572 |
+
Sporting Goods > Athletics > Tennis > Tennis Ball Hoppers & Carts
|
4573 |
+
Sporting Goods > Athletics > Tennis > Tennis Ball Machines
|
4574 |
+
Sporting Goods > Athletics > Tennis > Tennis Ball Savers
|
4575 |
+
Sporting Goods > Athletics > Tennis > Tennis Balls
|
4576 |
+
Sporting Goods > Athletics > Tennis > Tennis Nets
|
4577 |
+
Sporting Goods > Athletics > Tennis > Tennis Racquet Accessories
|
4578 |
+
Sporting Goods > Athletics > Tennis > Tennis Racquet Accessories > Racquet Vibration Dampeners
|
4579 |
+
Sporting Goods > Athletics > Tennis > Tennis Racquet Accessories > Tennis Racquet Bags
|
4580 |
+
Sporting Goods > Athletics > Tennis > Tennis Racquet Accessories > Tennis Racquet Grips & Tape
|
4581 |
+
Sporting Goods > Athletics > Tennis > Tennis Racquet Accessories > Tennis Racquet Grommets
|
4582 |
+
Sporting Goods > Athletics > Tennis > Tennis Racquet Accessories > Tennis Racquet String
|
4583 |
+
Sporting Goods > Athletics > Tennis > Tennis Racquets
|
4584 |
+
Sporting Goods > Athletics > Track & Field
|
4585 |
+
Sporting Goods > Athletics > Track & Field > Discus
|
4586 |
+
Sporting Goods > Athletics > Track & Field > High Jump Crossbars
|
4587 |
+
Sporting Goods > Athletics > Track & Field > High Jump Pits
|
4588 |
+
Sporting Goods > Athletics > Track & Field > Javelins
|
4589 |
+
Sporting Goods > Athletics > Track & Field > Pole Vault Pits
|
4590 |
+
Sporting Goods > Athletics > Track & Field > Relay Batons
|
4591 |
+
Sporting Goods > Athletics > Track & Field > Shot Puts
|
4592 |
+
Sporting Goods > Athletics > Track & Field > Starter Pistols
|
4593 |
+
Sporting Goods > Athletics > Track & Field > Throwing Hammers
|
4594 |
+
Sporting Goods > Athletics > Track & Field > Track Hurdles
|
4595 |
+
Sporting Goods > Athletics > Track & Field > Track Starting Blocks
|
4596 |
+
Sporting Goods > Athletics > Track & Field > Vaulting Poles
|
4597 |
+
Sporting Goods > Athletics > Volleyball
|
4598 |
+
Sporting Goods > Athletics > Volleyball > Volleyball Nets
|
4599 |
+
Sporting Goods > Athletics > Volleyball > Volleyball Protective Gear
|
4600 |
+
Sporting Goods > Athletics > Volleyball > Volleyball Protective Gear > Volleyball Knee Pads
|
4601 |
+
Sporting Goods > Athletics > Volleyball > Volleyball Training Aids
|
4602 |
+
Sporting Goods > Athletics > Volleyball > Volleyballs
|
4603 |
+
Sporting Goods > Athletics > Wallyball Equipment
|
4604 |
+
Sporting Goods > Athletics > Water Polo
|
4605 |
+
Sporting Goods > Athletics > Water Polo > Water Polo Balls
|
4606 |
+
Sporting Goods > Athletics > Water Polo > Water Polo Caps
|
4607 |
+
Sporting Goods > Athletics > Water Polo > Water Polo Goals
|
4608 |
+
Sporting Goods > Athletics > Wrestling
|
4609 |
+
Sporting Goods > Athletics > Wrestling > Wrestling Protective Gear
|
4610 |
+
Sporting Goods > Athletics > Wrestling > Wrestling Protective Gear > Wrestling Headgear
|
4611 |
+
Sporting Goods > Athletics > Wrestling > Wrestling Protective Gear > Wrestling Knee Pads
|
4612 |
+
Sporting Goods > Exercise & Fitness
|
4613 |
+
Sporting Goods > Exercise & Fitness > Ab Wheels & Rollers
|
4614 |
+
Sporting Goods > Exercise & Fitness > Aerobic Steps
|
4615 |
+
Sporting Goods > Exercise & Fitness > Balance Trainers
|
4616 |
+
Sporting Goods > Exercise & Fitness > Cardio
|
4617 |
+
Sporting Goods > Exercise & Fitness > Cardio > Cardio Machine Accessories
|
4618 |
+
Sporting Goods > Exercise & Fitness > Cardio > Cardio Machine Accessories > Elliptical Trainer Accessories
|
4619 |
+
Sporting Goods > Exercise & Fitness > Cardio > Cardio Machine Accessories > Exercise Bike Accessories
|
4620 |
+
Sporting Goods > Exercise & Fitness > Cardio > Cardio Machine Accessories > Rowing Machine Accessories
|
4621 |
+
Sporting Goods > Exercise & Fitness > Cardio > Cardio Machine Accessories > Stair Climber & Stepper Accessories
|
4622 |
+
Sporting Goods > Exercise & Fitness > Cardio > Cardio Machine Accessories > Treadmill Accessories
|
4623 |
+
Sporting Goods > Exercise & Fitness > Cardio > Cardio Machines
|
4624 |
+
Sporting Goods > Exercise & Fitness > Cardio > Cardio Machines > Elliptical Trainers
|
4625 |
+
Sporting Goods > Exercise & Fitness > Cardio > Cardio Machines > Exercise Bikes
|
4626 |
+
Sporting Goods > Exercise & Fitness > Cardio > Cardio Machines > Rowing Machines
|
4627 |
+
Sporting Goods > Exercise & Fitness > Cardio > Cardio Machines > Stair Climbers & Steppers
|
4628 |
+
Sporting Goods > Exercise & Fitness > Cardio > Cardio Machines > Stair Climbers & Steppers > Stair Climbers
|
4629 |
+
Sporting Goods > Exercise & Fitness > Cardio > Cardio Machines > Stair Climbers & Steppers > Stair Steppers
|
4630 |
+
Sporting Goods > Exercise & Fitness > Cardio > Cardio Machines > Treadmills
|
4631 |
+
Sporting Goods > Exercise & Fitness > Cardio > Jump Ropes
|
4632 |
+
Sporting Goods > Exercise & Fitness > Exercise Balls
|
4633 |
+
Sporting Goods > Exercise & Fitness > Exercise Bands
|
4634 |
+
Sporting Goods > Exercise & Fitness > Exercise Benches
|
4635 |
+
Sporting Goods > Exercise & Fitness > Exercise Equipment Mats
|
4636 |
+
Sporting Goods > Exercise & Fitness > Exercise Machine & Equipment Sets
|
4637 |
+
Sporting Goods > Exercise & Fitness > Exercise Wedges
|
4638 |
+
Sporting Goods > Exercise & Fitness > Foam Roller Accessories
|
4639 |
+
Sporting Goods > Exercise & Fitness > Foam Roller Accessories > Foam Roller Storage Bags
|
4640 |
+
Sporting Goods > Exercise & Fitness > Foam Rollers
|
4641 |
+
Sporting Goods > Exercise & Fitness > Hand Exercisers
|
4642 |
+
Sporting Goods > Exercise & Fitness > Inversion Tables & Systems
|
4643 |
+
Sporting Goods > Exercise & Fitness > Medicine Balls
|
4644 |
+
Sporting Goods > Exercise & Fitness > Power Towers
|
4645 |
+
Sporting Goods > Exercise & Fitness > Push Up & Pull Up Bars
|
4646 |
+
Sporting Goods > Exercise & Fitness > Reaction Balls
|
4647 |
+
Sporting Goods > Exercise & Fitness > Speed & Resistance Parachutes
|
4648 |
+
Sporting Goods > Exercise & Fitness > Sport Safety Lights & Reflectors
|
4649 |
+
Sporting Goods > Exercise & Fitness > Stopwatches
|
4650 |
+
Sporting Goods > Exercise & Fitness > Suspension Trainers
|
4651 |
+
Sporting Goods > Exercise & Fitness > Vibration Exercise Machines
|
4652 |
+
Sporting Goods > Exercise & Fitness > Weight Lifting
|
4653 |
+
Sporting Goods > Exercise & Fitness > Weight Lifting > Free Weight Accessories
|
4654 |
+
Sporting Goods > Exercise & Fitness > Weight Lifting > Free Weight Accessories > Free Weight Storage Racks
|
4655 |
+
Sporting Goods > Exercise & Fitness > Weight Lifting > Free Weight Accessories > Weight Bar Collars
|
4656 |
+
Sporting Goods > Exercise & Fitness > Weight Lifting > Free Weight Accessories > Weight Bars
|
4657 |
+
Sporting Goods > Exercise & Fitness > Weight Lifting > Free Weights
|
4658 |
+
Sporting Goods > Exercise & Fitness > Weight Lifting > Weight Lifting Belts
|
4659 |
+
Sporting Goods > Exercise & Fitness > Weight Lifting > Weight Lifting Gloves & Hand Supports
|
4660 |
+
Sporting Goods > Exercise & Fitness > Weight Lifting > Weight Lifting Machine & Exercise Bench Accessories
|
4661 |
+
Sporting Goods > Exercise & Fitness > Weight Lifting > Weight Lifting Machines & Racks
|
4662 |
+
Sporting Goods > Exercise & Fitness > Weighted Clothing
|
4663 |
+
Sporting Goods > Exercise & Fitness > Yoga & Pilates
|
4664 |
+
Sporting Goods > Exercise & Fitness > Yoga & Pilates > Pilates Machines
|
4665 |
+
Sporting Goods > Exercise & Fitness > Yoga & Pilates > Yoga & Pilates Blocks
|
4666 |
+
Sporting Goods > Exercise & Fitness > Yoga & Pilates > Yoga & Pilates Mats
|
4667 |
+
Sporting Goods > Exercise & Fitness > Yoga & Pilates > Yoga & Pilates Towels
|
4668 |
+
Sporting Goods > Exercise & Fitness > Yoga & Pilates > Yoga Mat Bags & Straps
|
4669 |
+
Sporting Goods > Indoor Games
|
4670 |
+
Sporting Goods > Indoor Games > Air Hockey
|
4671 |
+
Sporting Goods > Indoor Games > Air Hockey > Air Hockey Equipment
|
4672 |
+
Sporting Goods > Indoor Games > Air Hockey > Air Hockey Table Parts
|
4673 |
+
Sporting Goods > Indoor Games > Air Hockey > Air Hockey Tables
|
4674 |
+
Sporting Goods > Indoor Games > Billiards
|
4675 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Ball Racks
|
4676 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Balls
|
4677 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Cue Accessories
|
4678 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Cue Accessories > Billiard Cue Cases
|
4679 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Cue Accessories > Billiard Cue Chalk
|
4680 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Cue Accessories > Billiard Cue Racks
|
4681 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Cues & Bridges
|
4682 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Gloves
|
4683 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Table Lights
|
4684 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Table Parts & Accessories
|
4685 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Table Parts & Accessories > Billiard Pockets
|
4686 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Table Parts & Accessories > Billiard Table Brushes
|
4687 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Table Parts & Accessories > Billiard Table Cloth
|
4688 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Table Parts & Accessories > Billiard Table Covers
|
4689 |
+
Sporting Goods > Indoor Games > Billiards > Billiard Tables
|
4690 |
+
Sporting Goods > Indoor Games > Bowling
|
4691 |
+
Sporting Goods > Indoor Games > Bowling > Bowling Ball Bags
|
4692 |
+
Sporting Goods > Indoor Games > Bowling > Bowling Balls
|
4693 |
+
Sporting Goods > Indoor Games > Bowling > Bowling Gloves
|
4694 |
+
Sporting Goods > Indoor Games > Bowling > Bowling Pins
|
4695 |
+
Sporting Goods > Indoor Games > Bowling > Bowling Wrist Supports
|
4696 |
+
Sporting Goods > Indoor Games > Foosball
|
4697 |
+
Sporting Goods > Indoor Games > Foosball > Foosball Balls
|
4698 |
+
Sporting Goods > Indoor Games > Foosball > Foosball Table Parts & Accessories
|
4699 |
+
Sporting Goods > Indoor Games > Foosball > Foosball Tables
|
4700 |
+
Sporting Goods > Indoor Games > Multi-Game Tables
|
4701 |
+
Sporting Goods > Indoor Games > Ping Pong
|
4702 |
+
Sporting Goods > Indoor Games > Ping Pong > Ping Pong Balls
|
4703 |
+
Sporting Goods > Indoor Games > Ping Pong > Ping Pong Nets & Posts
|
4704 |
+
Sporting Goods > Indoor Games > Ping Pong > Ping Pong Paddle Accessories
|
4705 |
+
Sporting Goods > Indoor Games > Ping Pong > Ping Pong Paddles & Sets
|
4706 |
+
Sporting Goods > Indoor Games > Ping Pong > Ping Pong Robot Accessories
|
4707 |
+
Sporting Goods > Indoor Games > Ping Pong > Ping Pong Robots
|
4708 |
+
Sporting Goods > Indoor Games > Ping Pong > Ping Pong Tables
|
4709 |
+
Sporting Goods > Indoor Games > Table Shuffleboard
|
4710 |
+
Sporting Goods > Indoor Games > Table Shuffleboard > Shuffleboard Tables
|
4711 |
+
Sporting Goods > Indoor Games > Table Shuffleboard > Table Shuffleboard Powder
|
4712 |
+
Sporting Goods > Indoor Games > Table Shuffleboard > Table Shuffleboard Pucks
|
4713 |
+
Sporting Goods > Indoor Games > Throwing Darts
|
4714 |
+
Sporting Goods > Indoor Games > Throwing Darts > Dart Backboards
|
4715 |
+
Sporting Goods > Indoor Games > Throwing Darts > Dart Parts
|
4716 |
+
Sporting Goods > Indoor Games > Throwing Darts > Dart Parts > Dart Flights
|
4717 |
+
Sporting Goods > Indoor Games > Throwing Darts > Dart Parts > Dart Shafts
|
4718 |
+
Sporting Goods > Indoor Games > Throwing Darts > Dart Parts > Dart Tips
|
4719 |
+
Sporting Goods > Indoor Games > Throwing Darts > Dartboards
|
4720 |
+
Sporting Goods > Indoor Games > Throwing Darts > Darts
|
4721 |
+
Sporting Goods > Outdoor Recreation
|
4722 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports
|
4723 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting
|
4724 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Boating Gloves
|
4725 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Canoe Accessories
|
4726 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Canoes
|
4727 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Kayak Accessories
|
4728 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Kayaks
|
4729 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Paddle Leashes
|
4730 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Paddles & Oars
|
4731 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Pedal Boats
|
4732 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Row Boats
|
4733 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Rafting > Whitewater Rafts
|
4734 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel
|
4735 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Drysuits
|
4736 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Life Jacket Accessories
|
4737 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Life Jackets
|
4738 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Rash Guards & Swim Shirts
|
4739 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Water Sport Helmets
|
4740 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Wetsuit Pieces
|
4741 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Wetsuit Pieces > Wetsuit Bottoms
|
4742 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Wetsuit Pieces > Wetsuit Hoods, Gloves & Boots
|
4743 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Wetsuit Pieces > Wetsuit Tops
|
4744 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Boating & Water Sport Apparel > Wetsuits
|
4745 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling
|
4746 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Buoyancy Compensators
|
4747 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Dive Computers
|
4748 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Diving & Snorkeling Equipment Sets
|
4749 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Diving & Snorkeling Fins
|
4750 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Diving & Snorkeling Masks
|
4751 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Diving Belts
|
4752 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Diving Knives & Shears
|
4753 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Diving Regulators
|
4754 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Diving & Snorkeling > Snorkels
|
4755 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Kitesurfing
|
4756 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Kitesurfing > Kiteboard Cases
|
4757 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Kitesurfing > Kiteboard Parts
|
4758 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Kitesurfing > Kiteboards
|
4759 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Kitesurfing > Kitesurfing & Windsurfing Harnesses
|
4760 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Kitesurfing > Kitesurfing Kites
|
4761 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing
|
4762 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Bodyboards
|
4763 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Paddleboards
|
4764 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Skimboards
|
4765 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Surf Leashes
|
4766 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Surfboard Cases & Bags
|
4767 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Surfboard Fins
|
4768 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Surfboard Wax
|
4769 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Surfboards
|
4770 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Surfing Gloves
|
4771 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Surfing > Surfing Tail Pads
|
4772 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming
|
4773 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Child Swimming Aids
|
4774 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Hand Paddles
|
4775 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Kickboards
|
4776 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Pull Buoys
|
4777 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swim Belts
|
4778 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swim Caps
|
4779 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swim Gloves
|
4780 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swim Goggle & Mask Accessories
|
4781 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swim Goggles & Masks
|
4782 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swim Weights
|
4783 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swimming Fins
|
4784 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swimming Fins > Monofins
|
4785 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swimming Fins > Training Fins
|
4786 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swimming Machines
|
4787 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Swimming > Swimming Nose Clips
|
4788 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports
|
4789 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Kneeboarding
|
4790 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Kneeboarding > Kneeboards
|
4791 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Towable Rafts & Tubes
|
4792 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Towed Water Sport Gloves
|
4793 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Wakeboarding
|
4794 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Wakeboarding > Kiteboard & Wakeboard Bindings
|
4795 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Wakeboarding > Wakeboard Parts
|
4796 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Wakeboarding > Wakeboards
|
4797 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Water Skiing
|
4798 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Water Skiing > Sit-Down Hydrofoils
|
4799 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Water Skiing > Water Ski Bindings
|
4800 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Water Skiing > Water Ski Cases & Bags
|
4801 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Water Skiing > Water Skis
|
4802 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Towed Water Sports > Water Sport Tow Cables
|
4803 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Watercraft Storage Racks
|
4804 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Watercraft Storage Racks > Boat Storage Racks
|
4805 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Watercraft Storage Racks > Water Sport Board Storage Racks
|
4806 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Windsurfing
|
4807 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Windsurfing > Windsurfing Board Parts
|
4808 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Windsurfing > Windsurfing Board Parts > Windsurfing Board Fins
|
4809 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Windsurfing > Windsurfing Board Parts > Windsurfing Board Masts
|
4810 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Windsurfing > Windsurfing Boards
|
4811 |
+
Sporting Goods > Outdoor Recreation > Boating & Water Sports > Windsurfing > Windsurfing Sails
|
4812 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking
|
4813 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Camp Furniture
|
4814 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Camp Furniture > Air Mattress & Sleeping Pad Accessories
|
4815 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Camp Furniture > Air Mattresses
|
4816 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Camp Furniture > Cots
|
4817 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Camping Cookware & Dinnerware
|
4818 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Camping Lights & Lanterns
|
4819 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Camping Tools
|
4820 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Camping Tools > Hunting & Survival Knives
|
4821 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Camping Tools > Multifunction Tools & Knives
|
4822 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Chemical Hand Warmers
|
4823 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Compression Sacks
|
4824 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Hiking Pole Accessories
|
4825 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Hiking Poles
|
4826 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Mosquito Nets & Insect Screens
|
4827 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Navigational Compasses
|
4828 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Portable Toilets & Showers
|
4829 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Portable Toilets & Showers > Portable Showers & Privacy Enclosures
|
4830 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Portable Toilets & Showers > Portable Toilets & Urination Devices
|
4831 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Portable Water Filters & Purifiers
|
4832 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Sleeping Bag Liners
|
4833 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Sleeping Bags
|
4834 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Sleeping Pads
|
4835 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Tent Accessories
|
4836 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Tent Accessories > Inner Tents
|
4837 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Tent Accessories > Tent Footprints
|
4838 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Tent Accessories > Tent Poles & Stakes
|
4839 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Tent Accessories > Tent Vestibules
|
4840 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Tents
|
4841 |
+
Sporting Goods > Outdoor Recreation > Camping & Hiking > Windbreaks
|
4842 |
+
Sporting Goods > Outdoor Recreation > Climbing
|
4843 |
+
Sporting Goods > Outdoor Recreation > Climbing > Belay Devices
|
4844 |
+
Sporting Goods > Outdoor Recreation > Climbing > Carabiners
|
4845 |
+
Sporting Goods > Outdoor Recreation > Climbing > Climbing Apparel & Accessories
|
4846 |
+
Sporting Goods > Outdoor Recreation > Climbing > Climbing Apparel & Accessories > Climbing Gloves
|
4847 |
+
Sporting Goods > Outdoor Recreation > Climbing > Climbing Apparel & Accessories > Climbing Helmets
|
4848 |
+
Sporting Goods > Outdoor Recreation > Climbing > Climbing Apparel & Accessories > Crampons
|
4849 |
+
Sporting Goods > Outdoor Recreation > Climbing > Climbing Ascenders & Descenders
|
4850 |
+
Sporting Goods > Outdoor Recreation > Climbing > Climbing Chalk Bags
|
4851 |
+
Sporting Goods > Outdoor Recreation > Climbing > Climbing Crash Pads
|
4852 |
+
Sporting Goods > Outdoor Recreation > Climbing > Climbing Harnesses
|
4853 |
+
Sporting Goods > Outdoor Recreation > Climbing > Climbing Protection Devices
|
4854 |
+
Sporting Goods > Outdoor Recreation > Climbing > Climbing Rope
|
4855 |
+
Sporting Goods > Outdoor Recreation > Climbing > Climbing Rope Bags
|
4856 |
+
Sporting Goods > Outdoor Recreation > Climbing > Climbing Webbing
|
4857 |
+
Sporting Goods > Outdoor Recreation > Climbing > Ice Climbing Tools
|
4858 |
+
Sporting Goods > Outdoor Recreation > Climbing > Ice Screws
|
4859 |
+
Sporting Goods > Outdoor Recreation > Climbing > Indoor Climbing Holds
|
4860 |
+
Sporting Goods > Outdoor Recreation > Climbing > Quickdraws
|
4861 |
+
Sporting Goods > Outdoor Recreation > Cycling
|
4862 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories
|
4863 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Bags & Panniers
|
4864 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Baskets
|
4865 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Bells & Horns
|
4866 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Cages
|
4867 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Child Seat Accessories
|
4868 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Child Seats
|
4869 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Computer Accessories
|
4870 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Computers
|
4871 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Covers
|
4872 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Fenders
|
4873 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Front & Rear Racks
|
4874 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Handlebar Grips & Decor
|
4875 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Locks
|
4876 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Mirrors
|
4877 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Pumps
|
4878 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Saddle Pads & Seat Covers
|
4879 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Shock Pumps
|
4880 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Spoke Beads
|
4881 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Stands & Storage
|
4882 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Tire Repair Supplies & Kits
|
4883 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Toe Straps & Clips
|
4884 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Tools
|
4885 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Trailers
|
4886 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Trainers
|
4887 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Training Wheels
|
4888 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Transport Bags & Cases
|
4889 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Bicycle Water Sport Board Racks
|
4890 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Accessories > Electric Bicycle Conversion Kits
|
4891 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts
|
4892 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Brake Parts
|
4893 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Brake Parts > Bicycle Brake Calipers
|
4894 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Brake Parts > Bicycle Brake Levers
|
4895 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Brake Parts > Bicycle Brake Rotors
|
4896 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Brake Parts > Bicycle Brake Sets
|
4897 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Cable Housings
|
4898 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Cables
|
4899 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts
|
4900 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Bottom Brackets
|
4901 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Cassettes & Freewheels
|
4902 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Chainrings
|
4903 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Chains
|
4904 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Cranks
|
4905 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Derailleurs
|
4906 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Pedals
|
4907 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Drivetrain Parts > Bicycle Shifters
|
4908 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Forks
|
4909 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Frames
|
4910 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Groupsets
|
4911 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Handlebar Extensions
|
4912 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Handlebars
|
4913 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Headset Parts
|
4914 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Headset Parts > Bicycle Headset Bearings
|
4915 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Headset Parts > Bicycle Headset Spacers
|
4916 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Headsets
|
4917 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Kickstands
|
4918 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Saddles
|
4919 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Seatpost Clamps
|
4920 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Seatposts
|
4921 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Small Parts
|
4922 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Stems
|
4923 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Tire Valve Adapters
|
4924 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Tire Valve Caps
|
4925 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Tire Valves
|
4926 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Tires
|
4927 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Tubes
|
4928 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts
|
4929 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Foot Pegs
|
4930 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Hub Parts
|
4931 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Hubs
|
4932 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Rim Strips
|
4933 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Spokes
|
4934 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Wheel Axles & Skewers
|
4935 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Wheel Nipples
|
4936 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheel Parts > Bicycle Wheel Rims
|
4937 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycle Parts > Bicycle Wheels
|
4938 |
+
Sporting Goods > Outdoor Recreation > Cycling > Bicycles
|
4939 |
+
Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories
|
4940 |
+
Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Cleat Accessories
|
4941 |
+
Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Cleat Accessories > Bicycle Cleat Bolts
|
4942 |
+
Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Cleat Accessories > Bicycle Cleat Covers
|
4943 |
+
Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Cleat Accessories > Bicycle Cleat Shims & Wedges
|
4944 |
+
Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Cleats
|
4945 |
+
Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Gloves
|
4946 |
+
Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Helmet Parts & Accessories
|
4947 |
+
Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Helmets
|
4948 |
+
Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Protective Pads
|
4949 |
+
Sporting Goods > Outdoor Recreation > Cycling > Cycling Apparel & Accessories > Bicycle Shoe Covers
|
4950 |
+
Sporting Goods > Outdoor Recreation > Cycling > Tricycle Accessories
|
4951 |
+
Sporting Goods > Outdoor Recreation > Cycling > Tricycles
|
4952 |
+
Sporting Goods > Outdoor Recreation > Cycling > Unicycle Accessories
|
4953 |
+
Sporting Goods > Outdoor Recreation > Cycling > Unicycles
|
4954 |
+
Sporting Goods > Outdoor Recreation > Equestrian
|
4955 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Care
|
4956 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Blankets & Sheets
|
4957 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Boots & Leg Wraps
|
4958 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Feed
|
4959 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Fly Masks
|
4960 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Grooming
|
4961 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Grooming > Horse Clippers & Trimmers
|
4962 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Grooming > Horse Grooming Combs, Brushes & Mitts
|
4963 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Treats
|
4964 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Vitamins & Supplements
|
4965 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Care > Horse Wormers
|
4966 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack
|
4967 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Bridle Bits
|
4968 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Bridles
|
4969 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Cinches
|
4970 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Horse Halters
|
4971 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Horse Harnesses
|
4972 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Horse Leads
|
4973 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Reins
|
4974 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Saddles
|
4975 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack > Stirrups
|
4976 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories
|
4977 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories > Horse Tack Boxes
|
4978 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories > Saddle Accessories
|
4979 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories > Saddle Accessories > Saddle Bags & Panniers
|
4980 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories > Saddle Accessories > Saddle Covers & Cases
|
4981 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories > Saddle Accessories > Saddle Pads & Blankets
|
4982 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Horse Tack Accessories > Saddle Accessories > Saddle Racks
|
4983 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Riding Apparel & Accessories
|
4984 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Riding Apparel & Accessories > Equestrian Gloves
|
4985 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Riding Apparel & Accessories > Equestrian Helmets
|
4986 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Riding Apparel & Accessories > Riding Crops & Whips
|
4987 |
+
Sporting Goods > Outdoor Recreation > Equestrian > Riding Apparel & Accessories > Riding Pants
|
4988 |
+
Sporting Goods > Outdoor Recreation > Fishing
|
4989 |
+
Sporting Goods > Outdoor Recreation > Fishing > Bite Alarms
|
4990 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing & Hunting Waders
|
4991 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Bait & Chum Containers
|
4992 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Gaffs
|
4993 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Hook Removal Tools
|
4994 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Lines & Leaders
|
4995 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Nets
|
4996 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Reel Accessories
|
4997 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Reel Accessories > Fishing Reel Bags & Cases
|
4998 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Reel Accessories > Fishing Reel Lubricants
|
4999 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Reel Accessories > Fishing Reel Replacement Spools
|
5000 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Reels
|
5001 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Rod Accessories
|
5002 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Rod Accessories > Fishing Rod Bags & Cases
|
5003 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Rod Accessories > Fishing Rod Holders & Storage Racks
|
5004 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Rods
|
5005 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Spears
|
5006 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Tackle
|
5007 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Tackle > Fishing Baits & Lures
|
5008 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Tackle > Fishing Floats
|
5009 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Tackle > Fishing Hooks
|
5010 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Tackle > Fishing Sinkers
|
5011 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Tackle > Fishing Snaps & Swivels
|
5012 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fishing Traps
|
5013 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fly Tying Materials
|
5014 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fly Tying Materials > Fishing Beads
|
5015 |
+
Sporting Goods > Outdoor Recreation > Fishing > Fly Tying Materials > Fishing Yarn
|
5016 |
+
Sporting Goods > Outdoor Recreation > Fishing > Live Bait
|
5017 |
+
Sporting Goods > Outdoor Recreation > Fishing > Tackle Bags & Boxes
|
5018 |
+
Sporting Goods > Outdoor Recreation > Golf
|
5019 |
+
Sporting Goods > Outdoor Recreation > Golf > Divot Tools
|
5020 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Accessory Sets
|
5021 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Bag Accessories
|
5022 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Bag Accessories > Golf Bag Carts
|
5023 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Bag Accessories > Golf Bag Covers & Cases
|
5024 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Bags
|
5025 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Ball Markers
|
5026 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Balls
|
5027 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Club Parts & Accessories
|
5028 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Club Parts & Accessories > Golf Club Grips
|
5029 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Club Parts & Accessories > Golf Club Headcovers
|
5030 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Club Parts & Accessories > Golf Club Shafts
|
5031 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Clubs
|
5032 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Flags
|
5033 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Gloves
|
5034 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Tees
|
5035 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Towels
|
5036 |
+
Sporting Goods > Outdoor Recreation > Golf > Golf Training Aids
|
5037 |
+
Sporting Goods > Outdoor Recreation > Hang Gliding & Skydiving
|
5038 |
+
Sporting Goods > Outdoor Recreation > Hang Gliding & Skydiving > Air Suits
|
5039 |
+
Sporting Goods > Outdoor Recreation > Hang Gliding & Skydiving > Hang Gliders
|
5040 |
+
Sporting Goods > Outdoor Recreation > Hang Gliding & Skydiving > Parachutes
|
5041 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting
|
5042 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery
|
5043 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Archery Armguards
|
5044 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Archery Gloves & Releases
|
5045 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Archery Targets
|
5046 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Arrow Parts & Accessories
|
5047 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Arrow Parts & Accessories > Arrow Fletchings
|
5048 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Arrow Parts & Accessories > Arrow Nocks
|
5049 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Arrow Parts & Accessories > Broadheads & Field Points
|
5050 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Arrows & Bolts
|
5051 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Bow & Crossbow Accessories
|
5052 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Bows & Crossbows
|
5053 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Bows & Crossbows > Compound Bows
|
5054 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Bows & Crossbows > Crossbows
|
5055 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Bows & Crossbows > Recurve & Longbows
|
5056 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Archery > Quivers
|
5057 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Clay Pigeon Shooting
|
5058 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Clay Pigeon Shooting > Clay Pigeon Throwers
|
5059 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Clay Pigeon Shooting > Clay Pigeons
|
5060 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting
|
5061 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting & Shooting Protective Gear
|
5062 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting & Shooting Protective Gear > Hunting & Shooting Gloves
|
5063 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting & Shooting Protective Gear > Hunting & Shooting Jackets
|
5064 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Animal Traps
|
5065 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Hearing Enhancers
|
5066 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Hunting Blinds & Screens
|
5067 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Hunting Dog Equipment
|
5068 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Tree Stands
|
5069 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Wild Game Feeders
|
5070 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Wildlife Attractants
|
5071 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Wildlife Attractants > Cover Scents & Scent Attractants
|
5072 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Wildlife Attractants > Hunting & Wildlife Calls
|
5073 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Wildlife Attractants > Hunting & Wildlife Decoys
|
5074 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Hunting > Wildlife Attractants > Wildlife Bait, Feed & Minerals
|
5075 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft
|
5076 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Airsoft
|
5077 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Airsoft > Airsoft Gun Parts & Accessories
|
5078 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Airsoft > Airsoft Gun Parts & Accessories > Airsoft Gun Batteries
|
5079 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Airsoft > Airsoft Guns
|
5080 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Airsoft > Airsoft Pellets
|
5081 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball
|
5082 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball & Airsoft Protective Gear
|
5083 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball & Airsoft Protective Gear > Paintball & Airsoft Gloves
|
5084 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball & Airsoft Protective Gear > Paintball & Airsoft Goggles & Masks
|
5085 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball & Airsoft Protective Gear > Paintball & Airsoft Pads
|
5086 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball & Airsoft Protective Gear > Paintball & Airsoft Vests
|
5087 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Grenade Launchers
|
5088 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Grenades
|
5089 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Gun Parts & Accessories
|
5090 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Gun Parts & Accessories > Paintball Air Tanks
|
5091 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Gun Parts & Accessories > Paintball Gun Barrels
|
5092 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Gun Parts & Accessories > Paintball Gun Drop Forwards
|
5093 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Gun Parts & Accessories > Paintball Hoppers
|
5094 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Guns
|
5095 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintball Harnesses & Packs
|
5096 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Paintball & Airsoft > Paintball > Paintballs
|
5097 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Shooting & Range Accessories
|
5098 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Shooting & Range Accessories > Shooting Rests
|
5099 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Shooting & Range Accessories > Shooting Sticks & Bipods
|
5100 |
+
Sporting Goods > Outdoor Recreation > Hunting & Shooting > Shooting & Range Accessories > Shooting Targets
|
5101 |
+
Sporting Goods > Outdoor Recreation > Hydration System Accessories
|
5102 |
+
Sporting Goods > Outdoor Recreation > Hydration Systems
|
5103 |
+
Sporting Goods > Outdoor Recreation > Inline & Roller Skating
|
5104 |
+
Sporting Goods > Outdoor Recreation > Inline & Roller Skating > Inline & Roller Skating Protective Gear
|
5105 |
+
Sporting Goods > Outdoor Recreation > Inline & Roller Skating > Inline & Roller Skating Protective Gear > Roller Skating Pads
|
5106 |
+
Sporting Goods > Outdoor Recreation > Inline & Roller Skating > Inline Skate Parts
|
5107 |
+
Sporting Goods > Outdoor Recreation > Inline & Roller Skating > Inline Skates
|
5108 |
+
Sporting Goods > Outdoor Recreation > Inline & Roller Skating > Roller Skate Parts
|
5109 |
+
Sporting Goods > Outdoor Recreation > Inline & Roller Skating > Roller Skates
|
5110 |
+
Sporting Goods > Outdoor Recreation > Inline & Roller Skating > Roller Skis
|
5111 |
+
Sporting Goods > Outdoor Recreation > Kite Buggying
|
5112 |
+
Sporting Goods > Outdoor Recreation > Kite Buggying > Kite Buggies
|
5113 |
+
Sporting Goods > Outdoor Recreation > Kite Buggying > Kite Buggy Accessories
|
5114 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games
|
5115 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Badminton
|
5116 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Badminton > Badminton Nets
|
5117 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Badminton > Badminton Racquets & Sets
|
5118 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Badminton > Shuttlecocks
|
5119 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Deck Shuffleboard
|
5120 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Deck Shuffleboard > Deck Shuffleboard Cues
|
5121 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Deck Shuffleboard > Deck Shuffleboard Pucks
|
5122 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Disc Golf
|
5123 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Disc Golf > Disc Golf Bags
|
5124 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Disc Golf > Disc Golf Baskets
|
5125 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Lawn Games
|
5126 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Paddle Ball Sets
|
5127 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Pickleball
|
5128 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Pickleball > Pickleball Paddles
|
5129 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Pickleball > Pickleballs
|
5130 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Platform & Paddle Tennis
|
5131 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Platform & Paddle Tennis > Platform & Paddle Tennis Paddles
|
5132 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Platform & Paddle Tennis > Platform Tennis Balls
|
5133 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Tetherball
|
5134 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Tetherball > Tetherball Poles
|
5135 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Tetherball > Tetherball Sets
|
5136 |
+
Sporting Goods > Outdoor Recreation > Outdoor Games > Tetherball > Tetherballs
|
5137 |
+
Sporting Goods > Outdoor Recreation > Riding Scooters
|
5138 |
+
Sporting Goods > Outdoor Recreation > Skateboarding
|
5139 |
+
Sporting Goods > Outdoor Recreation > Skateboarding > Skate Rails
|
5140 |
+
Sporting Goods > Outdoor Recreation > Skateboarding > Skate Ramps
|
5141 |
+
Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Parts
|
5142 |
+
Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Parts > Skateboard Decks
|
5143 |
+
Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Parts > Skateboard Small Parts
|
5144 |
+
Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Parts > Skateboard Trucks
|
5145 |
+
Sporting Goods > Outdoor Recreation > Skateboarding > Skateboard Parts > Skateboard Wheels
|
5146 |
+
Sporting Goods > Outdoor Recreation > Skateboarding > Skateboarding Protective Gear
|
5147 |
+
Sporting Goods > Outdoor Recreation > Skateboarding > Skateboarding Protective Gear > Skate Helmets
|
5148 |
+
Sporting Goods > Outdoor Recreation > Skateboarding > Skateboarding Protective Gear > Skateboarding Gloves
|
5149 |
+
Sporting Goods > Outdoor Recreation > Skateboarding > Skateboarding Protective Gear > Skateboarding Pads
|
5150 |
+
Sporting Goods > Outdoor Recreation > Skateboarding > Skateboards
|
5151 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities
|
5152 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Avalanche Safety
|
5153 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Avalanche Safety > Avalanche Probes
|
5154 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Avalanche Safety > Avalanche Safety Airbags
|
5155 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding
|
5156 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Bags
|
5157 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Goggle Accessories
|
5158 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Goggle Accessories > Ski & Snowboard Goggle Lenses
|
5159 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Goggles
|
5160 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Helmets
|
5161 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Leashes
|
5162 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Storage Racks
|
5163 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Tuning Tools
|
5164 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski & Snowboard Wax
|
5165 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski Binding Parts
|
5166 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski Bindings
|
5167 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski Boots
|
5168 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Ski Poles
|
5169 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Skis
|
5170 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Skis > Cross-Country Skis
|
5171 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Skis > Downhill Skis
|
5172 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Snowboard Binding Parts
|
5173 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Snowboard Bindings
|
5174 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Snowboard Boots
|
5175 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Skiing & Snowboarding > Snowboards
|
5176 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Sleds
|
5177 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Snowshoeing
|
5178 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Snowshoeing > Snowshoe Bindings
|
5179 |
+
Sporting Goods > Outdoor Recreation > Winter Sports & Activities > Snowshoeing > Snowshoes
|
5180 |
+
Toys & Games
|
5181 |
+
Toys & Games > Game Timers
|
5182 |
+
Toys & Games > Games
|
5183 |
+
Toys & Games > Games > Battle Top Accessories
|
5184 |
+
Toys & Games > Games > Battle Tops
|
5185 |
+
Toys & Games > Games > Bingo Sets
|
5186 |
+
Toys & Games > Games > Blackjack & Craps Sets
|
5187 |
+
Toys & Games > Games > Board Games
|
5188 |
+
Toys & Games > Games > Card Game Accessories
|
5189 |
+
Toys & Games > Games > Card Games
|
5190 |
+
Toys & Games > Games > Dexterity Games
|
5191 |
+
Toys & Games > Games > Dice Sets & Games
|
5192 |
+
Toys & Games > Games > Poker Chip Accessories
|
5193 |
+
Toys & Games > Games > Poker Chip Accessories > Poker Chip Carriers & Trays
|
5194 |
+
Toys & Games > Games > Poker Chips & Sets
|
5195 |
+
Toys & Games > Games > Portable Electronic Games
|
5196 |
+
Toys & Games > Games > Roulette Wheels & Sets
|
5197 |
+
Toys & Games > Games > Slot Machines
|
5198 |
+
Toys & Games > Games > Tile Games
|
5199 |
+
Toys & Games > Outdoor Play Equipment
|
5200 |
+
Toys & Games > Outdoor Play Equipment > Inflatable Bouncer Accessories
|
5201 |
+
Toys & Games > Outdoor Play Equipment > Inflatable Bouncers
|
5202 |
+
Toys & Games > Outdoor Play Equipment > Play Swings
|
5203 |
+
Toys & Games > Outdoor Play Equipment > Play Tents & Tunnels
|
5204 |
+
Toys & Games > Outdoor Play Equipment > Playhouses
|
5205 |
+
Toys & Games > Outdoor Play Equipment > Pogo Sticks
|
5206 |
+
Toys & Games > Outdoor Play Equipment > Sandboxes
|
5207 |
+
Toys & Games > Outdoor Play Equipment > See Saws
|
5208 |
+
Toys & Games > Outdoor Play Equipment > Slides
|
5209 |
+
Toys & Games > Outdoor Play Equipment > Stilts
|
5210 |
+
Toys & Games > Outdoor Play Equipment > Swing Set & Playset Accessories
|
5211 |
+
Toys & Games > Outdoor Play Equipment > Swing Sets & Playsets
|
5212 |
+
Toys & Games > Outdoor Play Equipment > Trampoline Accessories
|
5213 |
+
Toys & Games > Outdoor Play Equipment > Trampolines
|
5214 |
+
Toys & Games > Outdoor Play Equipment > Water Play Equipment
|
5215 |
+
Toys & Games > Outdoor Play Equipment > Water Play Equipment > Play Sprinkers
|
5216 |
+
Toys & Games > Outdoor Play Equipment > Water Play Equipment > Water Parks & Slides
|
5217 |
+
Toys & Games > Outdoor Play Equipment > Water Play Equipment > Water Tables
|
5218 |
+
Toys & Games > Puzzles
|
5219 |
+
Toys & Games > Puzzles > Jigsaw Puzzle Accessories
|
5220 |
+
Toys & Games > Puzzles > Jigsaw Puzzles
|
5221 |
+
Toys & Games > Puzzles > Mechanical Puzzles
|
5222 |
+
Toys & Games > Puzzles > Wooden & Pegged Puzzles
|
5223 |
+
Toys & Games > Toys
|
5224 |
+
Toys & Games > Toys > Activity Toys
|
5225 |
+
Toys & Games > Toys > Activity Toys > Ball & Cup Games
|
5226 |
+
Toys & Games > Toys > Activity Toys > Bouncy Balls
|
5227 |
+
Toys & Games > Toys > Activity Toys > Bubble Blowing Solution
|
5228 |
+
Toys & Games > Toys > Activity Toys > Bubble Blowing Toys
|
5229 |
+
Toys & Games > Toys > Activity Toys > Coiled Spring Toys
|
5230 |
+
Toys & Games > Toys > Activity Toys > Marbles
|
5231 |
+
Toys & Games > Toys > Activity Toys > Paddle Ball Toys
|
5232 |
+
Toys & Games > Toys > Activity Toys > Ribbon & Streamer Toys
|
5233 |
+
Toys & Games > Toys > Activity Toys > Spinning Tops
|
5234 |
+
Toys & Games > Toys > Activity Toys > Toy Jacks
|
5235 |
+
Toys & Games > Toys > Activity Toys > Yo-Yo Parts & Accessories
|
5236 |
+
Toys & Games > Toys > Activity Toys > Yo-Yos
|
5237 |
+
Toys & Games > Toys > Art & Drawing Toys
|
5238 |
+
Toys & Games > Toys > Art & Drawing Toys > Play Dough & Putty
|
5239 |
+
Toys & Games > Toys > Art & Drawing Toys > Toy Drawing Tablets
|
5240 |
+
Toys & Games > Toys > Ball Pit Accessories
|
5241 |
+
Toys & Games > Toys > Ball Pit Accessories > Ball Pit Balls
|
5242 |
+
Toys & Games > Toys > Ball Pits
|
5243 |
+
Toys & Games > Toys > Bath Toys
|
5244 |
+
Toys & Games > Toys > Beach & Sand Toys
|
5245 |
+
Toys & Games > Toys > Building Toys
|
5246 |
+
Toys & Games > Toys > Building Toys > Construction Set Toys
|
5247 |
+
Toys & Games > Toys > Building Toys > Foam Blocks
|
5248 |
+
Toys & Games > Toys > Building Toys > Interlocking Blocks
|
5249 |
+
Toys & Games > Toys > Building Toys > Marble Track Sets
|
5250 |
+
Toys & Games > Toys > Building Toys > Wooden Blocks
|
5251 |
+
Toys & Games > Toys > Dolls, Playsets & Toy Figures
|
5252 |
+
Toys & Games > Toys > Dolls, Playsets & Toy Figures > Action & Toy Figures
|
5253 |
+
Toys & Games > Toys > Dolls, Playsets & Toy Figures > Bobblehead Figures
|
5254 |
+
Toys & Games > Toys > Dolls, Playsets & Toy Figures > Doll & Action Figure Accessories
|
5255 |
+
Toys & Games > Toys > Dolls, Playsets & Toy Figures > Dollhouse Accessories
|
5256 |
+
Toys & Games > Toys > Dolls, Playsets & Toy Figures > Dollhouses
|
5257 |
+
Toys & Games > Toys > Dolls, Playsets & Toy Figures > Dolls
|
5258 |
+
Toys & Games > Toys > Dolls, Playsets & Toy Figures > Paper & Magnetic Dolls
|
5259 |
+
Toys & Games > Toys > Dolls, Playsets & Toy Figures > Puppet & Puppet Theater Accessories
|
5260 |
+
Toys & Games > Toys > Dolls, Playsets & Toy Figures > Puppet Theaters
|
5261 |
+
Toys & Games > Toys > Dolls, Playsets & Toy Figures > Puppets & Marionettes
|
5262 |
+
Toys & Games > Toys > Dolls, Playsets & Toy Figures > Stuffed Animals
|
5263 |
+
Toys & Games > Toys > Dolls, Playsets & Toy Figures > Toy Playsets
|
5264 |
+
Toys & Games > Toys > Educational Toys
|
5265 |
+
Toys & Games > Toys > Educational Toys > Ant Farms
|
5266 |
+
Toys & Games > Toys > Educational Toys > Astronomy Toys & Models
|
5267 |
+
Toys & Games > Toys > Educational Toys > Bug Collecting Kits
|
5268 |
+
Toys & Games > Toys > Educational Toys > Educational Flash Cards
|
5269 |
+
Toys & Games > Toys > Educational Toys > Reading Toys
|
5270 |
+
Toys & Games > Toys > Educational Toys > Science & Exploration Sets
|
5271 |
+
Toys & Games > Toys > Educational Toys > Toy Abacuses
|
5272 |
+
Toys & Games > Toys > Executive Toys
|
5273 |
+
Toys & Games > Toys > Executive Toys > Magnet Toys
|
5274 |
+
Toys & Games > Toys > Flying Toy Accessories
|
5275 |
+
Toys & Games > Toys > Flying Toy Accessories > Kite Accessories
|
5276 |
+
Toys & Games > Toys > Flying Toy Accessories > Kite Accessories > Kite Line Reels & Winders
|
5277 |
+
Toys & Games > Toys > Flying Toys
|
5278 |
+
Toys & Games > Toys > Flying Toys > Air & Water Rockets
|
5279 |
+
Toys & Games > Toys > Flying Toys > Kites
|
5280 |
+
Toys & Games > Toys > Flying Toys > Toy Gliders
|
5281 |
+
Toys & Games > Toys > Flying Toys > Toy Parachutes
|
5282 |
+
Toys & Games > Toys > Musical Toys
|
5283 |
+
Toys & Games > Toys > Musical Toys > Toy Instruments
|
5284 |
+
Toys & Games > Toys > Play Vehicle Accessories
|
5285 |
+
Toys & Games > Toys > Play Vehicle Accessories > Toy Race Car & Track Accessories
|
5286 |
+
Toys & Games > Toys > Play Vehicle Accessories > Toy Train Accessories
|
5287 |
+
Toys & Games > Toys > Play Vehicles
|
5288 |
+
Toys & Games > Toys > Play Vehicles > Toy Airplanes
|
5289 |
+
Toys & Games > Toys > Play Vehicles > Toy Boats
|
5290 |
+
Toys & Games > Toys > Play Vehicles > Toy Cars
|
5291 |
+
Toys & Games > Toys > Play Vehicles > Toy Helicopters
|
5292 |
+
Toys & Games > Toys > Play Vehicles > Toy Motorcycles
|
5293 |
+
Toys & Games > Toys > Play Vehicles > Toy Race Car & Track Sets
|
5294 |
+
Toys & Games > Toys > Play Vehicles > Toy Spaceships
|
5295 |
+
Toys & Games > Toys > Play Vehicles > Toy Trains & Train Sets
|
5296 |
+
Toys & Games > Toys > Play Vehicles > Toy Trucks & Construction Vehicles
|
5297 |
+
Toys & Games > Toys > Pretend Play
|
5298 |
+
Toys & Games > Toys > Pretend Play > Play Money & Banking
|
5299 |
+
Toys & Games > Toys > Pretend Play > Pretend Electronics
|
5300 |
+
Toys & Games > Toys > Pretend Play > Pretend Housekeeping
|
5301 |
+
Toys & Games > Toys > Pretend Play > Pretend Lawn & Garden
|
5302 |
+
Toys & Games > Toys > Pretend Play > Pretend Professions & Role Playing
|
5303 |
+
Toys & Games > Toys > Pretend Play > Pretend Shopping & Grocery
|
5304 |
+
Toys & Games > Toys > Pretend Play > Toy Kitchens & Play Food
|
5305 |
+
Toys & Games > Toys > Pretend Play > Toy Kitchens & Play Food > Play Food
|
5306 |
+
Toys & Games > Toys > Pretend Play > Toy Kitchens & Play Food > Toy Cookware
|
5307 |
+
Toys & Games > Toys > Pretend Play > Toy Kitchens & Play Food > Toy Kitchens
|
5308 |
+
Toys & Games > Toys > Pretend Play > Toy Kitchens & Play Food > Toy Tableware
|
5309 |
+
Toys & Games > Toys > Pretend Play > Toy Tools
|
5310 |
+
Toys & Games > Toys > Remote Control Toy Accessories
|
5311 |
+
Toys & Games > Toys > Remote Control Toys
|
5312 |
+
Toys & Games > Toys > Remote Control Toys > Remote Control Airships & Blimps
|
5313 |
+
Toys & Games > Toys > Remote Control Toys > Remote Control Boats & Watercraft
|
5314 |
+
Toys & Games > Toys > Remote Control Toys > Remote Control Cars & Trucks
|
5315 |
+
Toys & Games > Toys > Remote Control Toys > Remote Control Helicopters
|
5316 |
+
Toys & Games > Toys > Remote Control Toys > Remote Control Motorcycles
|
5317 |
+
Toys & Games > Toys > Remote Control Toys > Remote Control Planes
|
5318 |
+
Toys & Games > Toys > Remote Control Toys > Remote Control Robots
|
5319 |
+
Toys & Games > Toys > Remote Control Toys > Remote Control Tanks
|
5320 |
+
Toys & Games > Toys > Riding Toy Accessories
|
5321 |
+
Toys & Games > Toys > Riding Toys
|
5322 |
+
Toys & Games > Toys > Riding Toys > Electric Riding Vehicles
|
5323 |
+
Toys & Games > Toys > Riding Toys > Hobby Horses
|
5324 |
+
Toys & Games > Toys > Riding Toys > Push & Pedal Riding Vehicles
|
5325 |
+
Toys & Games > Toys > Riding Toys > Rocking & Spring Riding Toys
|
5326 |
+
Toys & Games > Toys > Riding Toys > Wagons
|
5327 |
+
Toys & Games > Toys > Robotic Toys
|
5328 |
+
Toys & Games > Toys > Sports Toy Accessories
|
5329 |
+
Toys & Games > Toys > Sports Toy Accessories > Fitness Toy Accessories
|
5330 |
+
Toys & Games > Toys > Sports Toy Accessories > Fitness Toy Accessories > Hula Hoop Accessories
|
5331 |
+
Toys & Games > Toys > Sports Toys
|
5332 |
+
Toys & Games > Toys > Sports Toys > Baseball Toys
|
5333 |
+
Toys & Games > Toys > Sports Toys > Basketball Toys
|
5334 |
+
Toys & Games > Toys > Sports Toys > Boomerangs
|
5335 |
+
Toys & Games > Toys > Sports Toys > Bowling Toys
|
5336 |
+
Toys & Games > Toys > Sports Toys > Fingerboards & Fingerboard Sets
|
5337 |
+
Toys & Games > Toys > Sports Toys > Fishing Toys
|
5338 |
+
Toys & Games > Toys > Sports Toys > Fitness Toys
|
5339 |
+
Toys & Games > Toys > Sports Toys > Fitness Toys > Hula Hoops
|
5340 |
+
Toys & Games > Toys > Sports Toys > Flying Discs
|
5341 |
+
Toys & Games > Toys > Sports Toys > Footbags
|
5342 |
+
Toys & Games > Toys > Sports Toys > Golf Toys
|
5343 |
+
Toys & Games > Toys > Sports Toys > Hockey Toys
|
5344 |
+
Toys & Games > Toys > Sports Toys > Playground Balls
|
5345 |
+
Toys & Games > Toys > Sports Toys > Racquet Sport Toys
|
5346 |
+
Toys & Games > Toys > Sports Toys > Toy Footballs
|
5347 |
+
Toys & Games > Toys > Toy Gift Baskets
|
5348 |
+
Toys & Games > Toys > Toy Weapon & Gadget Accessories
|
5349 |
+
Toys & Games > Toys > Toy Weapons & Gadgets
|
5350 |
+
Toys & Games > Toys > Visual Toys
|
5351 |
+
Toys & Games > Toys > Visual Toys > Kaleidoscopes
|
5352 |
+
Toys & Games > Toys > Visual Toys > Prisms
|
5353 |
+
Toys & Games > Toys > Wind-Up Toys
|
5354 |
+
Vehicles & Parts
|
5355 |
+
Vehicles & Parts > Vehicle Parts & Accessories
|
5356 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Aircraft Parts & Accessories
|
5357 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics
|
5358 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle A/V Players & In-Dash Systems
|
5359 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Amplifiers
|
5360 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Cassette Adapters
|
5361 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Cassette Players
|
5362 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Equalizers & Crossovers
|
5363 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Parking Cameras
|
5364 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Speakerphones
|
5365 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Speakers
|
5366 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Subwoofers
|
5367 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Electronics > Motor Vehicle Video Monitor Mounts
|
5368 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts
|
5369 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Braking
|
5370 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Carpet & Upholstery
|
5371 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Climate Control
|
5372 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Controls
|
5373 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Oil Circulation
|
5374 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engine Parts
|
5375 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Engines
|
5376 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Exhaust
|
5377 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Frame & Body Parts
|
5378 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Fuel Systems
|
5379 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Interior Fittings
|
5380 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Lighting
|
5381 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Mirrors
|
5382 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Power & Electrical Systems
|
5383 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Seating
|
5384 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Sensors & Gauges
|
5385 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Suspension Parts
|
5386 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Towing
|
5387 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Transmission & Drivetrain Parts
|
5388 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems
|
5389 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Rims & Wheels
|
5390 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Rims & Wheels > Automotive Rims & Wheels
|
5391 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Rims & Wheels > Motorcycle Rims & Wheels
|
5392 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Rims & Wheels > Off-Road and All-Terrain Vehicle Rims & Wheels
|
5393 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Tire Accessories
|
5394 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Tires
|
5395 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Tires > Automotive Tires
|
5396 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Tires > Motorcycle Tires
|
5397 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Tires > Off-Road and All-Terrain Vehicle Tires
|
5398 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Wheel Systems > Motor Vehicle Wheel Parts
|
5399 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Motor Vehicle Parts > Motor Vehicle Window Parts & Accessories
|
5400 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor
|
5401 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Portable Fuel Cans
|
5402 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Cleaning
|
5403 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Cleaning > Car Wash Brushes
|
5404 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Cleaning > Car Wash Solutions
|
5405 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Cleaning > Vehicle Carpet & Upholstery Cleaners
|
5406 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Cleaning > Vehicle Fuel Injection Cleaning Kits
|
5407 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Cleaning > Vehicle Glass Cleaners
|
5408 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Cleaning > Vehicle Waxes, Polishes & Protectants
|
5409 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers
|
5410 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Golf Cart Enclosures
|
5411 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Motor Vehicle Windshield Covers
|
5412 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Tonneau Covers
|
5413 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Hardtops
|
5414 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Soft Tops
|
5415 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Storage Covers
|
5416 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Storage Covers > Automotive Storage Covers
|
5417 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Storage Covers > Golf Cart Storage Covers
|
5418 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Storage Covers > Motorcycle Storage Covers
|
5419 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Storage Covers > Recreational Vehicle Storage Covers
|
5420 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Covers > Vehicle Storage Covers > Watercraft Storage Covers
|
5421 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor
|
5422 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Bumper Stickers
|
5423 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Air Fresheners
|
5424 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Antenna Balls
|
5425 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Dashboard Accessories
|
5426 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Decals
|
5427 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Decor Accessory Sets
|
5428 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Display Flags
|
5429 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Emblems & Hood Ornaments
|
5430 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Hitch Covers
|
5431 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle License Plate Covers
|
5432 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle License Plate Frames
|
5433 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle License Plate Mounts & Holders
|
5434 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle License Plates
|
5435 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Magnets
|
5436 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Rear View Mirror Ornaments
|
5437 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Shift Boots
|
5438 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Shift Knobs
|
5439 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Steering Wheel Covers
|
5440 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Decor > Vehicle Wraps
|
5441 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids
|
5442 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Antifreeze
|
5443 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Brake Fluid
|
5444 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Cooling System Additives
|
5445 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Engine Degreasers
|
5446 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Fuel System Cleaners
|
5447 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Greases
|
5448 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Hydraulic Clutch Fluid
|
5449 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Motor Oil
|
5450 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Performance Additives
|
5451 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Power Steering Fluid
|
5452 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Transmission Fluid
|
5453 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Fluids > Vehicle Windshield Fluid
|
5454 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Paint
|
5455 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Paint > Motor Vehicle Body Paint
|
5456 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Paint > Motor Vehicle Brake Caliper Paint
|
5457 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools
|
5458 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Motor Vehicle Brake Service Kits
|
5459 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Motor Vehicle Clutch Alignment & Removal Tools
|
5460 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Vehicle Battery Chargers
|
5461 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Vehicle Battery Testers
|
5462 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Vehicle Body Filler
|
5463 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Vehicle Diagnostic Scanners
|
5464 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Vehicle Jump Starters
|
5465 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Vehicle Jumper Cables
|
5466 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Vehicle Tire Repair & Tire Changing Tools
|
5467 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Maintenance, Care & Decor > Vehicle Repair & Specialty Tools > Windshield Repair Kits
|
5468 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security
|
5469 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear
|
5470 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Chest & Back Protectors
|
5471 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Elbow & Wrist Guards
|
5472 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Gloves
|
5473 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Goggles
|
5474 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Hand Guards
|
5475 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Helmet Parts & Accessories
|
5476 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Helmets
|
5477 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Kidney Belts
|
5478 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Knee & Shin Guards
|
5479 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Motorcycle Protective Gear > Motorcycle Neck Braces
|
5480 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Off-Road & All-Terrain Vehicle Protective Gear
|
5481 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Off-Road & All-Terrain Vehicle Protective Gear > ATV & UTV Bar Pads
|
5482 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks
|
5483 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Automotive Alarm Accessories
|
5484 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Automotive Alarm Systems
|
5485 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Motorcycle Alarms & Locks
|
5486 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Door Locks & Parts
|
5487 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Door Locks & Parts > Vehicle Door Lock Actuators
|
5488 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Door Locks & Parts > Vehicle Door Lock Knobs
|
5489 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Door Locks & Parts > Vehicle Door Locks & Locking Systems
|
5490 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Hitch Locks
|
5491 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Immobilizers
|
5492 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Remote Keyless Systems
|
5493 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Steering Wheel Locks
|
5494 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Alarms & Locks > Vehicle Wheel Clamps
|
5495 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment
|
5496 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Car Window Nets
|
5497 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Emergency Road Flares
|
5498 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Motor Vehicle Airbag Parts
|
5499 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Motor Vehicle Roll Cages & Bars
|
5500 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Vehicle Seat Belt Buckles
|
5501 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Vehicle Seat Belt Covers
|
5502 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Vehicle Seat Belt Straps
|
5503 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Vehicle Seat Belts
|
5504 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Vehicle Warning Whips
|
5505 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Safety & Security > Vehicle Safety Equipment > Vehicle Wheel Chocks
|
5506 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo
|
5507 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Cargo Nets
|
5508 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Rack Accessories
|
5509 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Rack Accessories > Vehicle Bicycle Rack Accessories
|
5510 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Rack Accessories > Vehicle Ski & Snowboard Rack Accessories
|
5511 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks
|
5512 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Base Rack Systems
|
5513 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Bicycle Racks
|
5514 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Boat Racks
|
5515 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Cargo Racks
|
5516 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Fishing Rod Racks
|
5517 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Gun Racks
|
5518 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Motorcycle & Scooter Racks
|
5519 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Ski & Snowboard Racks
|
5520 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Carrying Racks > Vehicle Water Sport Board Racks
|
5521 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Loading Ramps
|
5522 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Trailers
|
5523 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Trailers > Boat Trailers
|
5524 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Trailers > Horse & Livestock Trailers
|
5525 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Trailers > Travel Trailers
|
5526 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motor Vehicle Trailers > Utility & Cargo Trailers
|
5527 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Motorcycle Bags & Panniers
|
5528 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Truck Bed Storage Boxes & Organizers
|
5529 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Vehicle Headrest Hangers & Hooks
|
5530 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Vehicle Storage & Cargo > Vehicle Organizers
|
5531 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories
|
5532 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Docking & Anchoring
|
5533 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Docking & Anchoring > Anchor Chains
|
5534 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Docking & Anchoring > Anchor Lines & Ropes
|
5535 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Docking & Anchoring > Anchor Windlasses
|
5536 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Docking & Anchoring > Anchors
|
5537 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Docking & Anchoring > Boat Hooks
|
5538 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Docking & Anchoring > Boat Ladders
|
5539 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Docking & Anchoring > Dock Cleats
|
5540 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Docking & Anchoring > Dock Steps
|
5541 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Sailboat Parts
|
5542 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Care
|
5543 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Care > Watercraft Cleaners
|
5544 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Care > Watercraft Polishes
|
5545 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Engine Parts
|
5546 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Engine Parts > Watercraft Alternators
|
5547 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Engine Parts > Watercraft Carburetors & Parts
|
5548 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Engine Parts > Watercraft Engine Controls
|
5549 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Engine Parts > Watercraft Ignition Parts
|
5550 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Engine Parts > Watercraft Impellers
|
5551 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Engine Parts > Watercraft Motor Locks
|
5552 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Engine Parts > Watercraft Motor Mounts
|
5553 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Engine Parts > Watercraft Pistons & Parts
|
5554 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Engine Parts > Watercraft Propellers
|
5555 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Engines & Motors
|
5556 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Exhaust Parts
|
5557 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Exhaust Parts > Watercraft Manifolds
|
5558 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Exhaust Parts > Watercraft Mufflers & Parts
|
5559 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Fuel Systems
|
5560 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Fuel Systems > Watercraft Fuel Lines & Parts
|
5561 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Fuel Systems > Watercraft Fuel Meters
|
5562 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Fuel Systems > Watercraft Fuel Pumps & Parts
|
5563 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Fuel Systems > Watercraft Fuel Tanks & Parts
|
5564 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Lighting
|
5565 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Steering Parts
|
5566 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Steering Parts > Watercraft Steering Cables
|
5567 |
+
Vehicles & Parts > Vehicle Parts & Accessories > Watercraft Parts & Accessories > Watercraft Steering Parts > Watercraft Steering Wheels
|
5568 |
+
Vehicles & Parts > Vehicles
|
5569 |
+
Vehicles & Parts > Vehicles > Aircraft
|
5570 |
+
Vehicles & Parts > Vehicles > Motor Vehicles
|
5571 |
+
Vehicles & Parts > Vehicles > Motor Vehicles > Cars, Trucks & Vans
|
5572 |
+
Vehicles & Parts > Vehicles > Motor Vehicles > Golf Carts
|
5573 |
+
Vehicles & Parts > Vehicles > Motor Vehicles > Motorcycles & Scooters
|
5574 |
+
Vehicles & Parts > Vehicles > Motor Vehicles > Off-Road and All-Terrain Vehicles
|
5575 |
+
Vehicles & Parts > Vehicles > Motor Vehicles > Off-Road and All-Terrain Vehicles > ATVs & UTVs
|
5576 |
+
Vehicles & Parts > Vehicles > Motor Vehicles > Off-Road and All-Terrain Vehicles > Go Karts & Dune Buggies
|
5577 |
+
Vehicles & Parts > Vehicles > Motor Vehicles > Recreational Vehicles
|
5578 |
+
Vehicles & Parts > Vehicles > Motor Vehicles > Snowmobiles
|
5579 |
+
Vehicles & Parts > Vehicles > Watercraft
|
5580 |
+
Vehicles & Parts > Vehicles > Watercraft > Motor Boats
|
5581 |
+
Vehicles & Parts > Vehicles > Watercraft > Personal Watercraft
|
5582 |
+
Vehicles & Parts > Vehicles > Watercraft > Sailboats
|
5583 |
+
Vehicles & Parts > Vehicles > Watercraft > Yachts
|
includes/application/google/tvc_google-source.js
ADDED
@@ -0,0 +1,292 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
var _googleClothingAndAccessories = false;
|
2 |
+
var _googleNeedsProductCat = false;
|
3 |
+
var _googleRequiresBrand = true;
|
4 |
+
|
5 |
+
// ALERT! This function is equivalent for the woocommerce_to_feed_fields() function in class-data.php
|
6 |
+
function woocommerceToGoogleFields() {
|
7 |
+
return {
|
8 |
+
'id': 'ID',
|
9 |
+
'title': 'post_title',
|
10 |
+
'google_product_category': 'category',
|
11 |
+
'description': 'post_content',
|
12 |
+
'link': 'permalink',
|
13 |
+
'image_link': 'attachment_url',
|
14 |
+
'additional_image_link': '_wp_attachement_metadata',
|
15 |
+
'price': '_regular_price',
|
16 |
+
'sale_price': '_sale_price',
|
17 |
+
'sale_price_effective_date': '_sale_price_dates_from',
|
18 |
+
'item_group_id': 'item_group_id',
|
19 |
+
'mpn': 'ID',
|
20 |
+
'tax': 'Use the settings in the Merchant Center',
|
21 |
+
'shipping': 'Use the settings in the Merchant Center',
|
22 |
+
};
|
23 |
+
}
|
24 |
+
|
25 |
+
// ALERT! This function is equivalent for the set_google_output_attribute_levels() function in class-data.php
|
26 |
+
function setGoogleOutputAttributeLevels( feedHolder, targetCountry ) {
|
27 |
+
for ( var i = 0; i < feedHolder[ 'attributes' ].length; i ++ ) {
|
28 |
+
|
29 |
+
if ( feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] === '0' ) {
|
30 |
+
|
31 |
+
switch ( feedHolder[ 'attributes' ][ i ][ 'fieldName' ] ) {
|
32 |
+
|
33 |
+
case 'google_product_category':
|
34 |
+
|
35 |
+
if ( _googleNeedsProductCat === true ) {
|
36 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '1';
|
37 |
+
} else {
|
38 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '4';
|
39 |
+
}
|
40 |
+
|
41 |
+
break;
|
42 |
+
|
43 |
+
case 'is_bundle':
|
44 |
+
case 'multipack':
|
45 |
+
|
46 |
+
if ( jQuery.inArray( targetCountry, googleSpecialProductCountries() ) < 0 ) {
|
47 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '4';
|
48 |
+
} else {
|
49 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '1';
|
50 |
+
}
|
51 |
+
|
52 |
+
break;
|
53 |
+
|
54 |
+
case 'brand':
|
55 |
+
|
56 |
+
if ( _googleRequiresBrand === true ) {
|
57 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '1';
|
58 |
+
} else {
|
59 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '4';
|
60 |
+
}
|
61 |
+
|
62 |
+
break;
|
63 |
+
|
64 |
+
case 'item_group_id':
|
65 |
+
|
66 |
+
if ( jQuery.inArray( targetCountry, googleSpecialClothingGroupCountries() ) > - 1 ) {
|
67 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '1';
|
68 |
+
} else {
|
69 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '4';
|
70 |
+
}
|
71 |
+
|
72 |
+
break;
|
73 |
+
|
74 |
+
case 'gender':
|
75 |
+
case 'age_group':
|
76 |
+
case 'color':
|
77 |
+
case 'size':
|
78 |
+
|
79 |
+
if ( jQuery.inArray( targetCountry, googleSpecialClothingGroupCountries() ) > - 1 && _googleClothingAndAccessories === true ) {
|
80 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '1';
|
81 |
+
} else {
|
82 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '4';
|
83 |
+
}
|
84 |
+
|
85 |
+
break;
|
86 |
+
|
87 |
+
case 'tax':
|
88 |
+
|
89 |
+
// In accordance with the Google Feed Specifications update of september 2015
|
90 |
+
if ( targetCountry === 'US' ) {
|
91 |
+
|
92 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '1';
|
93 |
+
} else {
|
94 |
+
|
95 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '4';
|
96 |
+
}
|
97 |
+
|
98 |
+
break;
|
99 |
+
|
100 |
+
case 'shipping':
|
101 |
+
|
102 |
+
// In accordance with the Google Feed Specifications update of september 2015
|
103 |
+
if ( jQuery.inArray( targetCountry, googleSpecialShippingCountries() ) > - 1 ) {
|
104 |
+
|
105 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '1';
|
106 |
+
} else {
|
107 |
+
|
108 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '4';
|
109 |
+
}
|
110 |
+
|
111 |
+
break;
|
112 |
+
|
113 |
+
case 'subscription_costs':
|
114 |
+
case 'subscription_cost-period':
|
115 |
+
case 'subscription_cost-period_length':
|
116 |
+
case 'subscription_cost-amount':
|
117 |
+
|
118 |
+
if ( jQuery.inArray( targetCountry, googleSpecialSubscriptionCountries()) > - 1 ) {
|
119 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '4';
|
120 |
+
} else {
|
121 |
+
feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] = '0';
|
122 |
+
}
|
123 |
+
|
124 |
+
break;
|
125 |
+
|
126 |
+
default:
|
127 |
+
break;
|
128 |
+
|
129 |
+
}
|
130 |
+
|
131 |
+
// set the attribute to active if it's a recommended or highly recommended attribute, or if it has a value
|
132 |
+
feedHolder[ 'attributes' ][ i ][ 'isActive' ] = setAttributeStatus( parseInt( feedHolder[ 'attributes' ][ i ][ 'fieldLevel' ] ), feedHolder[ 'attributes' ][ i ][ 'value' ] );
|
133 |
+
}
|
134 |
+
}
|
135 |
+
|
136 |
+
return feedHolder;
|
137 |
+
}
|
138 |
+
|
139 |
+
function setGooglePresets( field ) {
|
140 |
+
switch ( field ) {
|
141 |
+
case 'condition':
|
142 |
+
return '{"m":[{"s":{"static":"new"}}]}';
|
143 |
+
|
144 |
+
case 'availability':
|
145 |
+
return '{"m":[{"s":{"static":"in stock"},"c":[{"1":"0#_stock_status#0#instock"}]},{"s":{"static":"out of stock"}}]}';
|
146 |
+
|
147 |
+
case 'identifier_exists':
|
148 |
+
return '{"m":[{"s":{"static":"yes"}}]}';
|
149 |
+
|
150 |
+
case 'adult':
|
151 |
+
return '{"m":[{"s":{"static":"no"}}]}';
|
152 |
+
|
153 |
+
case 'price':
|
154 |
+
return '{"m":[{"s":{"source":"combined","f":"_regular_price|1#wc_currency"}}]}';
|
155 |
+
|
156 |
+
default:
|
157 |
+
break;
|
158 |
+
}
|
159 |
+
}
|
160 |
+
|
161 |
+
function fillGoogleCategoryVariables( selectedCategory, currentLevel ) {
|
162 |
+
switch ( currentLevel ) {
|
163 |
+
case 'lvl_0':
|
164 |
+
case 'lvl_1':
|
165 |
+
_googleClothingAndAccessories = false;
|
166 |
+
_googleNeedsProductCat = false;
|
167 |
+
_googleRequiresBrand = true;
|
168 |
+
break;
|
169 |
+
}
|
170 |
+
|
171 |
+
switch ( selectedCategory ) {
|
172 |
+
case 'Clothing':
|
173 |
+
_googleClothingAndAccessories = true;
|
174 |
+
_googleNeedsProductCat = true;
|
175 |
+
_googleRequiresBrand = true;
|
176 |
+
break;
|
177 |
+
|
178 |
+
case 'Software':
|
179 |
+
case 'Apparel & Accessories':
|
180 |
+
_googleClothingAndAccessories = true;
|
181 |
+
_googleNeedsProductCat = true;
|
182 |
+
_googleRequiresBrand = true;
|
183 |
+
break;
|
184 |
+
|
185 |
+
case 'Media':
|
186 |
+
_googleClothingAndAccessories = false;
|
187 |
+
_googleNeedsProductCat = true;
|
188 |
+
_googleRequiresBrand = false;
|
189 |
+
break;
|
190 |
+
|
191 |
+
default:
|
192 |
+
break;
|
193 |
+
}
|
194 |
+
}
|
195 |
+
|
196 |
+
function googleStaticFieldOptions( fieldName ) {
|
197 |
+
var options = [];
|
198 |
+
|
199 |
+
switch ( fieldName ) {
|
200 |
+
case 'condition':
|
201 |
+
options = [ 'new', 'used', 'refurbished' ];
|
202 |
+
break;
|
203 |
+
|
204 |
+
case 'availability':
|
205 |
+
options = [ 'in stock', 'out of stock', 'preorder' ];
|
206 |
+
break;
|
207 |
+
|
208 |
+
case 'identifier_exists':
|
209 |
+
options = [ 'yes', 'no' ];
|
210 |
+
break;
|
211 |
+
|
212 |
+
case 'gender':
|
213 |
+
options = [ 'unisex', 'male', 'female' ];
|
214 |
+
break;
|
215 |
+
|
216 |
+
case 'age_group':
|
217 |
+
options = [ 'adult', 'newborn', 'infant', 'toddler', 'kids' ];
|
218 |
+
break;
|
219 |
+
|
220 |
+
case 'size_type':
|
221 |
+
options = [ 'regular', 'petite', 'plus', 'big and tall', 'maternity' ];
|
222 |
+
break;
|
223 |
+
|
224 |
+
case 'size_system':
|
225 |
+
options = [ 'EU', 'US', 'UK', 'DE', 'FR', 'JP', 'CN', 'IT', 'BR', 'MEX', 'AU' ];
|
226 |
+
break;
|
227 |
+
|
228 |
+
case 'adult':
|
229 |
+
options = [ 'yes', 'no' ];
|
230 |
+
break;
|
231 |
+
|
232 |
+
case 'energy_efficiency_class':
|
233 |
+
case 'min_energy_efficiency_class':
|
234 |
+
case 'max_energy_efficiency_class':
|
235 |
+
options = [ 'A', 'A+', 'A++', 'A+++', 'B', 'C', 'D', 'E', 'F', 'G' ];
|
236 |
+
break;
|
237 |
+
|
238 |
+
case 'excluded_destination':
|
239 |
+
options = [ 'Shopping', 'ShoppingActions', 'DisplayAds' ];
|
240 |
+
break;
|
241 |
+
|
242 |
+
default:
|
243 |
+
options = [];
|
244 |
+
break;
|
245 |
+
}
|
246 |
+
|
247 |
+
return options;
|
248 |
+
}
|
249 |
+
|
250 |
+
function switchToGoogleFeedFormMainInputs( isNew, channel ) {
|
251 |
+
jQuery( '#country-list-row' ).show();
|
252 |
+
jQuery( '#category-list-row' ).show();
|
253 |
+
jQuery( '#google-feed-title-row' ).show();
|
254 |
+
jQuery( '#google-feed-description-row' ).show();
|
255 |
+
jQuery( '#aggregator-selector-row' ).hide();
|
256 |
+
|
257 |
+
appendCategoryLists( parseInt( channel ), 'en-US', isNew );
|
258 |
+
}
|
259 |
+
|
260 |
+
function googleInputChanged( feedId, categoryChanged ) {
|
261 |
+
var fileName = jQuery( '#file-name' ).val();
|
262 |
+
var selectedCountry = jQuery( '#countries' ).val();
|
263 |
+
var selectedMainCategory = jQuery( '#lvl_0' ).val();
|
264 |
+
|
265 |
+
// enable or disable the correct buttons for the google channel
|
266 |
+
if ( fileName && selectedCountry !== '0' && selectedMainCategory && selectedMainCategory !== '0' ) {
|
267 |
+
updateFeedFormAfterInputChanged( feedId, categoryChanged );
|
268 |
+
} else {
|
269 |
+
// keep the Generate and Save buttons disabled
|
270 |
+
disableFeedActionButtons();
|
271 |
+
}
|
272 |
+
}
|
273 |
+
|
274 |
+
// ALERT! This function is equivalent to the special_clothing_group_countries() function in class-feed.php in the google channels folder
|
275 |
+
function googleSpecialClothingGroupCountries() {
|
276 |
+
return [ 'US', 'GB', 'DE', 'FR', 'JP', 'BR' ]; // Brazil added based on the new Feed Specifications from september 2015
|
277 |
+
}
|
278 |
+
|
279 |
+
// ALERT! This function is equivalent to the special_shipping_countries() function in class-feed.php in the google channels folder
|
280 |
+
function googleSpecialShippingCountries() {
|
281 |
+
return [ 'US', 'GB', 'DE', 'AU', 'FR', 'CH', 'CZ', 'NL', 'IT', 'ES', 'JP' ];
|
282 |
+
}
|
283 |
+
|
284 |
+
// ALERT! This function is equivalent to the special_product_countries() function in class-feed.php in the google channels folder
|
285 |
+
function googleSpecialProductCountries() {
|
286 |
+
return [ 'US', 'GB', 'DE', 'AU', 'FR', 'CH', 'CZ', 'NL', 'IT', 'ES', 'JP', 'BR' ];
|
287 |
+
}
|
288 |
+
|
289 |
+
// ALERT! This function is equivalent to the special_subscription_countries() function in class-feed.php in the google channels folder
|
290 |
+
function googleSpecialSubscriptionCountries() {
|
291 |
+
return [ 'DE', 'FR', 'GB' ];
|
292 |
+
}
|
includes/application/js/tvc_channel-functions.js
ADDED
@@ -0,0 +1,707 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"use strict";
|
2 |
+
/**
|
3 |
+
* Switches the correct input fields on the feed form on or off depending on the selected channel
|
4 |
+
*
|
5 |
+
* @param {string} channel
|
6 |
+
* @param {boolean} isNew
|
7 |
+
* @returns nothing
|
8 |
+
*/
|
9 |
+
|
10 |
+
// TVC_CHANNEL_RELATED
|
11 |
+
function tvc_showChannelInputs( channel, isNew ) {
|
12 |
+
var fName = {
|
13 |
+
'1': 'switchToGoogleFeedFormMainInputs',
|
14 |
+
'2': 'switchToBingFeedFormMainInputs',
|
15 |
+
'3': 'switchToBeslisFeedFormMainInputs',
|
16 |
+
'4': 'switchToPricegrabberFeedFormMainInputs',
|
17 |
+
'5': 'switchToShoppingFeedFormMainInputs',
|
18 |
+
'6': 'switchToAmazonFeedFormMainInputs',
|
19 |
+
'7': 'switchToConnexityFeedFormMainInputs',
|
20 |
+
'9': 'switchToNextagFeedFormMainInputs',
|
21 |
+
'10': 'switchToKieskeurigFeedFormMainInputs',
|
22 |
+
'11': 'switchToVergelijkFeedFormMainInputs',
|
23 |
+
'12': 'switchToKoopjespakkerFeedFormMainInputs',
|
24 |
+
'13': 'switchToAvantLinkFeedFormMainInputs',
|
25 |
+
'14': 'switchToZboziFeedFormMainInputs',
|
26 |
+
'15': 'switchToComconFeedFormMainInputs',
|
27 |
+
'16': 'switchToFacebookFeedFormMainInputs',
|
28 |
+
'17': 'switchToBolFeedFormMainInputs',
|
29 |
+
'18': 'switchToAdtractionFeedFormMainInputs',
|
30 |
+
'19': 'switchToRicardoFeedFormMainInputs',
|
31 |
+
'20': 'switchToEbayFeedFormMainInputs',
|
32 |
+
'21': 'switchToShopzillaFeedFormMainInputs',
|
33 |
+
'22': 'switchToConvertoFeedFormMainInputs',
|
34 |
+
'23': 'switchToIdealoFeedFormMainInputs',
|
35 |
+
'24': 'switchToHeurekaFeedFormMainInputs',
|
36 |
+
'25': 'switchToPepperjamFeedFormMainInputs',
|
37 |
+
'26': 'switchToGalaxusProductDataFeedFormMainInputs',
|
38 |
+
'27': 'switchToGalaxusProductPropertiesFeedFormMainInputs',
|
39 |
+
'28': 'switchToGalaxusProductStockPricingFeedFormMainInputs',
|
40 |
+
'996': 'switchToTsvFeedFormMainInputs',
|
41 |
+
'997': 'switchToTxtFeedFormMainInputs',
|
42 |
+
'998': 'switchToCsvFeedFormMainInputs',
|
43 |
+
'999': 'switchToFeedFormMainInputs',
|
44 |
+
};
|
45 |
+
|
46 |
+
// call the correct function
|
47 |
+
if ( fName.hasOwnProperty( channel ) ) {
|
48 |
+
window[ fName[ channel ] ]( isNew, channel );
|
49 |
+
}
|
50 |
+
|
51 |
+
// standard for all channels
|
52 |
+
jQuery( '#update-schedule-row' ).show();
|
53 |
+
jQuery( '#add-product-variations-row' ).show();
|
54 |
+
|
55 |
+
if ( (
|
56 |
+
null === jQuery( '#lvl_0' ).val() && '' === jQuery( '#selected-categories' ).html() ) || 0 === jQuery( '#tvc-countries-selector' ).val() ) {
|
57 |
+
tvc_show_or_hide_category_map( channel );
|
58 |
+
} else {
|
59 |
+
jQuery( '#tvc-category-map' ).show();
|
60 |
+
}
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* depending on channel show or hide the category map directly after channel selection
|
65 |
+
* Add the channel to the "show" part when it does not have an own category list
|
66 |
+
*
|
67 |
+
* @param {string} channel
|
68 |
+
* @returns nothing
|
69 |
+
*/
|
70 |
+
function tvc_show_or_hide_category_map( channel ) {
|
71 |
+
var category_map_selector = jQuery( '#tvc-category-map' );
|
72 |
+
|
73 |
+
switch ( channel ) {
|
74 |
+
case '15': // Commerce Connector
|
75 |
+
case '17': // Bol.com
|
76 |
+
case '18': // Adtraction
|
77 |
+
case '22': // Converto
|
78 |
+
case '23': // Idealo
|
79 |
+
case '25': // Pepperjam
|
80 |
+
case '26': // Galaxus Product Data
|
81 |
+
case '27': // Galaxus Product Stock Pricing
|
82 |
+
case '28': // Galaxus Product Properties
|
83 |
+
category_map_selector.show();
|
84 |
+
break;
|
85 |
+
|
86 |
+
default:
|
87 |
+
category_map_selector.hide();
|
88 |
+
break;
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Usually categories are separated by a > but some channels use other separators
|
94 |
+
*
|
95 |
+
* @since 2.2.0
|
96 |
+
*
|
97 |
+
* @param {string} channel
|
98 |
+
* @returns {string} separator
|
99 |
+
*/
|
100 |
+
function tvc_category_separator( channel ) {
|
101 |
+
switch ( channel ) {
|
102 |
+
case '14': // Commerce Connector
|
103 |
+
case '24': // Commerce Connector
|
104 |
+
return ' | ';
|
105 |
+
|
106 |
+
default:
|
107 |
+
return ' > ';
|
108 |
+
}
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* calls the correct channel function that makes sure the correct input fields are shown after the user has changed the title or channel
|
113 |
+
*
|
114 |
+
* @param {string} channel
|
115 |
+
* @param {string} feedId
|
116 |
+
* @param {boolean} categoryChanged
|
117 |
+
* @returns nothing
|
118 |
+
*/
|
119 |
+
function tvc_reactOnChannelInputChanged( channel, feedId, categoryChanged ) {
|
120 |
+
var functionName = '';
|
121 |
+
var tabId = tvc_getUrlVariable( 'tab' ); // identify the feed type
|
122 |
+
|
123 |
+
if ( 'product-feed' === tabId ) { // handle product feeds from different merchants
|
124 |
+
var fName = {
|
125 |
+
'1': 'googleInputChanged',
|
126 |
+
'2': 'bingInputChanged',
|
127 |
+
'3': 'beslisInputChanged',
|
128 |
+
'4': 'pricegrabberInputChanged',
|
129 |
+
'5': 'shoppingInputChanged',
|
130 |
+
'6': 'amazonInputChanged',
|
131 |
+
'7': 'connexityInputChanged',
|
132 |
+
'9': 'nextagInputChanged',
|
133 |
+
'10': 'kieskeurigInputChanged',
|
134 |
+
'11': 'vergelijkInputChanged',
|
135 |
+
'12': 'koopjespakkerInputChanged',
|
136 |
+
'13': 'avantlinkInputChanged',
|
137 |
+
'14': 'zboziInputChanged',
|
138 |
+
'15': 'comconInputChanged',
|
139 |
+
'16': 'facebookInputChanged',
|
140 |
+
'17': 'bolInputChanged',
|
141 |
+
'18': 'adtractionInputChanged',
|
142 |
+
'19': 'ricardoInputChanged',
|
143 |
+
'20': 'ebayInputChanged',
|
144 |
+
'21': 'shopzillaInputChanged',
|
145 |
+
'22': 'convertoInputChanged',
|
146 |
+
'23': 'idealoInputChanged',
|
147 |
+
'24': 'heurekaInputChanged',
|
148 |
+
'25': 'pepperjamInputChanged',
|
149 |
+
'26': 'galaxusProductDataInputChanged',
|
150 |
+
'27': 'galaxusProductStockPricingInputChanged',
|
151 |
+
'28': 'galaxusProductPropertiesInputChanged',
|
152 |
+
'996': 'TsvInputChanged',
|
153 |
+
'997': 'TxtInputChanged',
|
154 |
+
'998': 'CsvInputChanged',
|
155 |
+
'999': 'InputChanged',
|
156 |
+
};
|
157 |
+
|
158 |
+
functionName = fName[ channel ];
|
159 |
+
} else { // handle special feeds from add-ons
|
160 |
+
var functionString = tvc_convertToCamelCase( tabId.split( '-' ) );
|
161 |
+
functionName = functionString + 'Changed';
|
162 |
+
}
|
163 |
+
|
164 |
+
// call the correct function
|
165 |
+
if ( functionName ) {
|
166 |
+
window[ functionName ]( feedId, categoryChanged );
|
167 |
+
}
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Returns txt of xml depending on the feed type that needs to be made
|
172 |
+
*
|
173 |
+
* @param {string} channel
|
174 |
+
* @returns {string} with the channel feed type
|
175 |
+
*/
|
176 |
+
function tvc_getChannelFeedType( channel ) {
|
177 |
+
switch ( channel ) {
|
178 |
+
case '2': // bing
|
179 |
+
case '4': // pricegrabber
|
180 |
+
case '6': // amazon
|
181 |
+
case '7': // connexity
|
182 |
+
case '9': // nextag
|
183 |
+
case '12': // koopjespakker.nl
|
184 |
+
case '21': // shopzilla
|
185 |
+
case '25': // pepperjam
|
186 |
+
case '997': // Custom TXT Feed
|
187 |
+
return 'txt';
|
188 |
+
|
189 |
+
case '15': // Commerce Connector
|
190 |
+
case '17': // Bol.com
|
191 |
+
case '19': // Ricardo.ch
|
192 |
+
case '22': // Converto
|
193 |
+
case '23': // Idealo
|
194 |
+
case '26': // Galaxus Product Data
|
195 |
+
case '27': // Galaxus Product Stock Pricing
|
196 |
+
case '28': // Galaxus Product Properties
|
197 |
+
case '998': // Custom CSV Feed
|
198 |
+
return 'csv';
|
199 |
+
|
200 |
+
case '996': // Custom TSV feed
|
201 |
+
return 'tsv';
|
202 |
+
|
203 |
+
default:
|
204 |
+
return 'xml';
|
205 |
+
}
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* returns the correct country code for the channel specific category text file
|
210 |
+
*
|
211 |
+
* @param {string} channel
|
212 |
+
* @returns {String} with the channels country code
|
213 |
+
*/
|
214 |
+
function tvc_channelCountryCode( channel ) {
|
215 |
+
var language = 'en-US';
|
216 |
+
|
217 |
+
// TVC_CHANNEL_RELATED
|
218 |
+
switch ( channel ) {
|
219 |
+
case '3': // Beslist
|
220 |
+
case '10': // Kieskeurig
|
221 |
+
case '11': // Vergelijk
|
222 |
+
case '12': // Koopjespakker
|
223 |
+
case '17': // Bol.com
|
224 |
+
language = 'nl-NL';
|
225 |
+
break;
|
226 |
+
|
227 |
+
case '14': // Zbozi
|
228 |
+
case '24': // Heureka
|
229 |
+
language = 'cs-CZ';
|
230 |
+
break;
|
231 |
+
|
232 |
+
case '19': // Ricardo.ch
|
233 |
+
language = 'de-CH';
|
234 |
+
break;
|
235 |
+
|
236 |
+
case '23': // Idealo
|
237 |
+
language = 'de-DE';
|
238 |
+
break;
|
239 |
+
}
|
240 |
+
|
241 |
+
return language;
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* Returns true if the specified channel does not have its own categories but uses the users shop
|
246 |
+
* categories instead
|
247 |
+
*
|
248 |
+
* @param {string} channel
|
249 |
+
* @returns {Boolean} true when this channel uses categories from the shop
|
250 |
+
*/
|
251 |
+
function tvc_channelUsesOwnCategories( channel ) {
|
252 |
+
// only add the channel when it uses the shop categories in stead of specific channel categories
|
253 |
+
switch ( channel ) {
|
254 |
+
case '10': // kieskeurig.nl
|
255 |
+
case '15': // Commerce Connector
|
256 |
+
case '17': // Bol.com
|
257 |
+
case '18': // Adtraction
|
258 |
+
case '22': // Converto
|
259 |
+
case '23': // Idealo
|
260 |
+
case '25': // Pepperjam
|
261 |
+
case '26': // Galaxus Product Data
|
262 |
+
case '27': // Galaxus Product Stock Pricing
|
263 |
+
case '28': // Galaxus Product Properties
|
264 |
+
return true;
|
265 |
+
|
266 |
+
default:
|
267 |
+
return false;
|
268 |
+
}
|
269 |
+
}
|
270 |
+
|
271 |
+
/**
|
272 |
+
* If required for that channel, this function activates the correct function that will prepare the global category
|
273 |
+
* variables in the channel specific javascript file. Does nothing when not required for the channel
|
274 |
+
*
|
275 |
+
* @param {string} channel
|
276 |
+
* @param {string} selectedCategory
|
277 |
+
* @param {string} currentLevelId
|
278 |
+
* @returns nothing
|
279 |
+
*/
|
280 |
+
function tvc_fillCategoryVariables(
|
281 |
+
channel, selectedCategory, currentLevelId ) {
|
282 |
+
var fName = {
|
283 |
+
'1': 'fillGoogleCategoryVariables',
|
284 |
+
'4': 'fillPricegrabberCategoryVariables',
|
285 |
+
'5': 'fillShoppingCategoryVariables',
|
286 |
+
'6': 'fillAmazonCategoryVariables',
|
287 |
+
'7': 'fillConnexityCategoryVariables',
|
288 |
+
'9': 'fillNextagCategoryVariables',
|
289 |
+
'13': 'fillAvantLinkCategoryVariables',
|
290 |
+
'14': 'fillZboziCategoryVariables',
|
291 |
+
};
|
292 |
+
|
293 |
+
// call the correct function
|
294 |
+
if ( fName.hasOwnProperty( channel ) ) {
|
295 |
+
// call the correct switch main form inputs function
|
296 |
+
window[ fName[ channel ] ]( selectedCategory, currentLevelId );
|
297 |
+
}
|
298 |
+
}
|
299 |
+
|
300 |
+
/**
|
301 |
+
* Some fields require specific allowed inputs. This function gets the correct options for given field
|
302 |
+
*
|
303 |
+
* @param {string} rowId
|
304 |
+
* @param {string} queryLevel
|
305 |
+
* @param {string} combinationLevel
|
306 |
+
* @param {string} channel
|
307 |
+
* @param {string} fieldName
|
308 |
+
* @param {string} selectedValue
|
309 |
+
* @returns {String} containing the allowed options
|
310 |
+
*/
|
311 |
+
function tvc_displayCorrectStaticField(
|
312 |
+
rowId, queryLevel, combinationLevel, channel, fieldName, selectedValue ) {
|
313 |
+
var html = '';
|
314 |
+
var options = tvc_restrictedStaticFields( channel, fieldName );
|
315 |
+
|
316 |
+
if ( options !== undefined ) {
|
317 |
+
if ( options.length === 0 ) {
|
318 |
+
// show the standard text type input field
|
319 |
+
html = tvc_staticInputField( rowId, queryLevel, combinationLevel, selectedValue );
|
320 |
+
} else {
|
321 |
+
// show the standard selector with the correct allowed options
|
322 |
+
html = tvc_staticInputSelect( rowId, queryLevel, combinationLevel, options, selectedValue );
|
323 |
+
}
|
324 |
+
}
|
325 |
+
|
326 |
+
return html;
|
327 |
+
}
|
328 |
+
|
329 |
+
/**
|
330 |
+
* Gets the advised input fields
|
331 |
+
*
|
332 |
+
* @param {string} channel
|
333 |
+
* @returns {array} array containing the advised inputs
|
334 |
+
*/
|
335 |
+
function tvc_getAdvisedInputs( channel ) {
|
336 |
+
var fName = {
|
337 |
+
'1': 'woocommerceToGoogleFields',
|
338 |
+
'2': 'woocommerceToBingFields',
|
339 |
+
'3': 'woocommerceToBeslisFields',
|
340 |
+
'4': 'woocommerceToPricegrabberFields',
|
341 |
+
'5': 'woocommerceToShoppingFields',
|
342 |
+
'6': 'woocommerceToAmazonFields',
|
343 |
+
'7': 'woocommerceToConnexityFields',
|
344 |
+
'9': 'woocommerceToNextagFields',
|
345 |
+
'10': 'woocommerceToKieskeurigFields',
|
346 |
+
'11': 'woocommerceToVergelijkFields',
|
347 |
+
'12': 'woocommerceToKoopjespakkerFields',
|
348 |
+
'13': 'woocommerceToAvantLinkFields',
|
349 |
+
'14': 'woocommerceToZboziFields',
|
350 |
+
'15': 'woocommerceToComconFields',
|
351 |
+
'16': 'woocommerceToFacebookFields',
|
352 |
+
'17': 'woocommerceToBolFields',
|
353 |
+
'18': 'woocommerceToAdtractionFields',
|
354 |
+
'19': 'woocommerceToRicardoFields',
|
355 |
+
'20': 'woocommerceToeBayFields',
|
356 |
+
'21': 'woocommerceToShopzillaFields',
|
357 |
+
'22': 'woocommerceToConvertoFields',
|
358 |
+
'23': 'woocommerceToIdealoFields',
|
359 |
+
'24': 'woocommerceToHeurekaFields',
|
360 |
+
'25': 'woocommerceToPepperjamFields',
|
361 |
+
'26': 'woocommerceToGalaxusProductDataFields',
|
362 |
+
'27': 'woocommerceToGalaxusProductStockPricingFields',
|
363 |
+
'28': 'woocommerceToGalaxusProductPropertiesFields',
|
364 |
+
};
|
365 |
+
|
366 |
+
if ( fName.hasOwnProperty( channel ) ) {
|
367 |
+
// call the correct function
|
368 |
+
return window[ fName[ channel ] ]();
|
369 |
+
} else {
|
370 |
+
return [];
|
371 |
+
}
|
372 |
+
}
|
373 |
+
|
374 |
+
/**
|
375 |
+
* Sets the attributes to the correct levels depending on several variables.
|
376 |
+
*
|
377 |
+
* @param {string} channel Channel id.
|
378 |
+
* @param {object} feedHolder Feed Holder containing feed data items.
|
379 |
+
* @param {string} selectArgument
|
380 |
+
*
|
381 |
+
* @returns {object} feed holder with the correct attribute levels
|
382 |
+
*/
|
383 |
+
// ALERT has a relation with the set_output_attribute_levels() function in the class-tvc-data.php file
|
384 |
+
function tvc_setOutputAttributeLevels( channel, feedHolder, selectArgument ) {
|
385 |
+
switch ( channel ) {
|
386 |
+
case '1':
|
387 |
+
return setGoogleOutputAttributeLevels( feedHolder, selectArgument );
|
388 |
+
|
389 |
+
case '2':
|
390 |
+
return setBingOutputAttributeLevels( feedHolder );
|
391 |
+
|
392 |
+
case '3':
|
393 |
+
return setBeslisOutputAttributeLevels( feedHolder );
|
394 |
+
|
395 |
+
case '4':
|
396 |
+
return setPricegrabberOutputAttributeLevels( feedHolder );
|
397 |
+
|
398 |
+
case '5':
|
399 |
+
return setShoppingOutputAttributeLevels( feedHolder );
|
400 |
+
|
401 |
+
case '6':
|
402 |
+
return setAmazonOutputAttributeLevels( feedHolder );
|
403 |
+
|
404 |
+
case '7':
|
405 |
+
return setConnexityOutputAttributeLevels( feedHolder );
|
406 |
+
|
407 |
+
case '9':
|
408 |
+
return setNextagOutputAttributeLevels( feedHolder );
|
409 |
+
|
410 |
+
case '10':
|
411 |
+
return setKieskeurigOutputAttributeLevels( feedHolder );
|
412 |
+
|
413 |
+
case '11':
|
414 |
+
return setVergelijkOutputAttributeLevels( feedHolder );
|
415 |
+
|
416 |
+
case '13':
|
417 |
+
return setAvantLinkOutputAttributeLevels( feedHolder,
|
418 |
+
selectArgument );
|
419 |
+
|
420 |
+
case '14':
|
421 |
+
return setZboziOutputAttributeLevels( feedHolder, selectArgument );
|
422 |
+
|
423 |
+
case '26':
|
424 |
+
return setGalaxusProductDataAttributeLevels( feedHolder,
|
425 |
+
selectArgument );
|
426 |
+
|
427 |
+
case '27':
|
428 |
+
return setGalaxusProductStockPricingAttributeLevels( feedHolder );
|
429 |
+
|
430 |
+
case '28':
|
431 |
+
return setGalaxusProductPropertiesAttributeLevels( feedHolder );
|
432 |
+
|
433 |
+
case '996':
|
434 |
+
return setTsvOutputAttributeLevels( feedHolder );
|
435 |
+
|
436 |
+
case '997':
|
437 |
+
return setTxtOutputAttributeLevels( feedHolder );
|
438 |
+
|
439 |
+
case '998':
|
440 |
+
return setCsvOutputAttributeLevels( feedHolder );
|
441 |
+
|
442 |
+
case '999':
|
443 |
+
return setOutputAttributeLevels( feedHolder );
|
444 |
+
|
445 |
+
default:
|
446 |
+
return feedHolder;
|
447 |
+
}
|
448 |
+
}
|
449 |
+
|
450 |
+
/**
|
451 |
+
* returns an array with the channel specific fields with restricted input options
|
452 |
+
*
|
453 |
+
* @param {string} channel
|
454 |
+
* @param {string} fieldName
|
455 |
+
* @returns {array}
|
456 |
+
*/
|
457 |
+
function tvc_restrictedStaticFields( channel, fieldName ) {
|
458 |
+
var fName = {
|
459 |
+
'1': 'googleStaticFieldOptions',
|
460 |
+
'2': 'bingStaticFieldOptions',
|
461 |
+
'3': 'beslisStaticFieldOptions',
|
462 |
+
'4': 'pricegrabberStaticFieldOptions',
|
463 |
+
'5': 'shoppingStaticFieldOptions',
|
464 |
+
'6': 'amazonStaticFieldOptions',
|
465 |
+
'7': 'connexityStaticFieldOptions',
|
466 |
+
'9': 'nextagStaticFieldOptions',
|
467 |
+
'10': 'kieskeurigStaticFieldOptions',
|
468 |
+
'11': 'vergelijkStaticFieldOptions',
|
469 |
+
'12': 'koopjespakkerStaticFieldOptions',
|
470 |
+
'13': 'avantlinkStaticFieldOptions',
|
471 |
+
'14': 'zboziStaticFieldOptions',
|
472 |
+
'15': 'comconStaticFieldOptions',
|
473 |
+
'16': 'facebookStaticFieldOptions',
|
474 |
+
'17': 'bolStaticFieldOptions',
|
475 |
+
'18': 'adtractionStaticFieldOptions',
|
476 |
+
'19': 'ricardoStaticFieldOptions',
|
477 |
+
'20': 'ebayStaticFieldOptions',
|
478 |
+
'21': 'shopzillaStaticFieldOptions',
|
479 |
+
'23': 'idealoStaticFieldOptions',
|
480 |
+
'25': 'pepperjamStaticFieldOptions',
|
481 |
+
'26': 'galaxusProductDataStaticFieldOptions',
|
482 |
+
'27': 'galaxusProductStockPricingStaticFieldOptions',
|
483 |
+
'28': 'galaxusProductPropertiesStaticFieldOptions',
|
484 |
+
};
|
485 |
+
|
486 |
+
if ( fName.hasOwnProperty( channel ) ) {
|
487 |
+
// call the correct function
|
488 |
+
return window[ fName[ channel ] ]( fieldName );
|
489 |
+
} else {
|
490 |
+
|
491 |
+
return [];
|
492 |
+
}
|
493 |
+
}
|
494 |
+
|
495 |
+
/**
|
496 |
+
* set a preset condition, other than the advised input, for fields for a specific channel (eg. condition = static field with 'new' selected
|
497 |
+
*
|
498 |
+
* @param {array} outputsField
|
499 |
+
* @param {string} channel
|
500 |
+
* @returns {array}
|
501 |
+
*/
|
502 |
+
function tvc_setChannelRelatedPresets( outputsField, channel ) {
|
503 |
+
// TVC_CHANNEL_RELATED
|
504 |
+
switch ( channel ) {
|
505 |
+
|
506 |
+
case '1': // Google
|
507 |
+
if ( outputsField[ 'field_label' ] === 'condition' || outputsField[ 'field_label' ] === 'availability' || outputsField[ 'field_label' ] === 'identifier_exists' || outputsField[ 'field_label' ] === 'adult' || outputsField[ 'field_label' ] === 'price' ) {
|
508 |
+
|
509 |
+
// only switch to the 'preset' value if no user value is set
|
510 |
+
if ( ! outputsField[ 'value' ] ) {
|
511 |
+
outputsField[ 'value' ] = setGooglePresets( outputsField[ 'field_label' ] );
|
512 |
+
}
|
513 |
+
}
|
514 |
+
break;
|
515 |
+
|
516 |
+
case '2': // Bing
|
517 |
+
if ( outputsField[ 'field_label' ] === 'seller_name' ) {
|
518 |
+
// only switch to the 'preset' value if no user value is set
|
519 |
+
if ( ! outputsField[ 'value' ] ) {
|
520 |
+
outputsField[ 'value' ] = setBingPresets( outputsField[ 'field_label' ] );
|
521 |
+
}
|
522 |
+
}
|
523 |
+
break;
|
524 |
+
|
525 |
+
case '3': // Beslist
|
526 |
+
if ( outputsField[ 'field_label' ] === 'Conditie' || outputsField[ 'field_label' ] === 'Levertijd' ) {
|
527 |
+
// only switch to the 'preset' value if no user value is set
|
528 |
+
if ( ! outputsField[ 'value' ] ) {
|
529 |
+
outputsField[ 'value' ] = setBeslisPresets( outputsField[ 'field_label' ] );
|
530 |
+
}
|
531 |
+
}
|
532 |
+
break;
|
533 |
+
|
534 |
+
case '13': // Avant Link
|
535 |
+
if ( outputsField[ 'field_label' ] === 'condition' || outputsField[ 'field_label' ] === 'availability' || outputsField[ 'field_label' ] === 'identifier_exists' ) {
|
536 |
+
|
537 |
+
// only switch to the 'preset' value if no user value is set
|
538 |
+
if ( ! outputsField[ 'value' ] ) {
|
539 |
+
outputsField[ 'value' ] = setAvantLinkPresets( outputsField[ 'field_label' ] );
|
540 |
+
}
|
541 |
+
}
|
542 |
+
break;
|
543 |
+
|
544 |
+
case '14': // Zbozi
|
545 |
+
if ( outputsField[ 'field_label' ] === 'EROTIC' || outputsField[ 'field_label' ] === 'VISIBILITY' ) {
|
546 |
+
// only switch to the 'preset' value if no user value is set
|
547 |
+
if ( ! outputsField[ 'value' ] ) {
|
548 |
+
outputsField[ 'value' ] = setZboziPresets( outputsField[ 'field_label' ] );
|
549 |
+
}
|
550 |
+
}
|
551 |
+
break;
|
552 |
+
|
553 |
+
case '15': // Commerce Connector
|
554 |
+
if ( outputsField[ 'field_label' ] === 'Delivery time' ) {
|
555 |
+
// only switch to the 'preset' value if no user value is set
|
556 |
+
if ( ! outputsField[ 'value' ] ) {
|
557 |
+
outputsField[ 'value' ] = setComconPresets( outputsField[ 'field_label' ] );
|
558 |
+
}
|
559 |
+
}
|
560 |
+
break;
|
561 |
+
|
562 |
+
case '16': // Facebook
|
563 |
+
if ( outputsField[ 'field_label' ] === 'condition' || outputsField[ 'field_label' ] === 'availability' || outputsField[ 'field_label' ] === 'price' ) {
|
564 |
+
|
565 |
+
// only switch to the 'preset' value if no user value is set
|
566 |
+
if ( ! outputsField[ 'value' ] ) {
|
567 |
+
outputsField[ 'value' ] = setFacebookPresets( outputsField[ 'field_label' ] );
|
568 |
+
}
|
569 |
+
}
|
570 |
+
break;
|
571 |
+
|
572 |
+
case '17': // Bol.com
|
573 |
+
if ( outputsField[ 'field_label' ] === 'Condition' || outputsField[ 'field_label' ] === 'Deliverycode' ) {
|
574 |
+
// only switch to the 'preset' value if no user value is set
|
575 |
+
if ( ! outputsField[ 'value' ] ) {
|
576 |
+
outputsField[ 'value' ] = setBolPresets( outputsField[ 'field_label' ] );
|
577 |
+
}
|
578 |
+
}
|
579 |
+
break;
|
580 |
+
|
581 |
+
case '18': // Adtraction
|
582 |
+
if ( outputsField[ 'field_label' ] === 'instock' ) {
|
583 |
+
// only switch to the 'preset' value if no user value is set
|
584 |
+
if ( ! outputsField[ 'value' ] ) {
|
585 |
+
outputsField[ 'value' ] = setAdtractionPresets( outputsField[ 'field_label' ] );
|
586 |
+
}
|
587 |
+
}
|
588 |
+
break;
|
589 |
+
|
590 |
+
case '19': // Ricardo
|
591 |
+
if ( outputsField[ 'field_label' ] === 'Descriptions[0].LanguageNr' || outputsField[ 'field_label' ] === 'Increment' || outputsField[ 'field_label' ] === 'AvailabilityId' || outputsField[ 'field_label' ] === 'Condition' ) {
|
592 |
+
|
593 |
+
// only switch to the 'preset' value if no user value is set
|
594 |
+
if ( ! outputsField[ 'value' ] ) {
|
595 |
+
outputsField[ 'value' ] = setRicardoPresets( outputsField[ 'field_label' ] );
|
596 |
+
}
|
597 |
+
}
|
598 |
+
break;
|
599 |
+
|
600 |
+
case '20': // eBay
|
601 |
+
break;
|
602 |
+
|
603 |
+
case '21': // Shopzilla
|
604 |
+
if ( outputsField[ 'field_label' ] === 'Availability' || outputsField[ 'field_label' ] === 'Condition' ) {
|
605 |
+
// only switch to the 'preset' value if no user value is set
|
606 |
+
if ( ! outputsField[ 'value' ] ) {
|
607 |
+
outputsField[ 'value' ] = setShopzillaPresets( outputsField[ 'field_label' ] );
|
608 |
+
}
|
609 |
+
}
|
610 |
+
break;
|
611 |
+
|
612 |
+
case '22': // Converto
|
613 |
+
if ( outputsField[ 'field_label' ] === 'Availability' || outputsField[ 'field_label' ] === 'Condition' ) {
|
614 |
+
// only switch to the 'preset' value if no user value is set
|
615 |
+
if ( ! outputsField[ 'value' ] ) {
|
616 |
+
outputsField[ 'value' ] = setShopzillaPresets( outputsField[ 'field_label' ] );
|
617 |
+
}
|
618 |
+
}
|
619 |
+
break;
|
620 |
+
|
621 |
+
case '24': // Heureka
|
622 |
+
if ( 'ITEM_TYPE' === outputsField[ 'field_label' ] ) {
|
623 |
+
if ( ! outputsField[ 'value' ] ) {
|
624 |
+
outputsField[ 'value' ] = setHeurekaPresets( outputsField[ 'field_label' ] );
|
625 |
+
}
|
626 |
+
}
|
627 |
+
break;
|
628 |
+
|
629 |
+
case '25': // Pepperjam
|
630 |
+
if ( 'ITEM_TYPE' === outputsField[ 'discontinued' ] ) {
|
631 |
+
if ( ! outputsField[ 'value' ] ) {
|
632 |
+
outputsField[ 'value' ] = setPepperjamPresets( outputsField[ 'field_label' ] );
|
633 |
+
}
|
634 |
+
}
|
635 |
+
break;
|
636 |
+
|
637 |
+
case '26': // Galaxus Product Data
|
638 |
+
if ( 'ITEM_TYPE' === outputsField[ 'discontinued' ] ) {
|
639 |
+
if ( ! outputsField[ 'value' ] ) {
|
640 |
+
outputsField[ 'value' ] = setGalaxusProductDataPresets( outputsField[ 'field_label' ] );
|
641 |
+
}
|
642 |
+
}
|
643 |
+
break;
|
644 |
+
|
645 |
+
case '27': // Galaxus Product Stock Pricing
|
646 |
+
if ( 'ITEM_TYPE' === outputsField[ 'discontinued' ] ) {
|
647 |
+
if ( ! outputsField[ 'value' ] ) {
|
648 |
+
outputsField[ 'value' ] = setGalaxusProductStockPricingPresets( outputsField[ 'field_label' ] );
|
649 |
+
}
|
650 |
+
}
|
651 |
+
break;
|
652 |
+
|
653 |
+
case '28': // Galaxus Product Properties
|
654 |
+
if ( 'ITEM_TYPE' === outputsField[ 'discontinued' ] ) {
|
655 |
+
if ( ! outputsField[ 'value' ] ) {
|
656 |
+
outputsField[ 'value' ] = setGalaxusProductPropertiesPresets( outputsField[ 'field_label' ] );
|
657 |
+
}
|
658 |
+
}
|
659 |
+
break;
|
660 |
+
|
661 |
+
default:
|
662 |
+
break;
|
663 |
+
}
|
664 |
+
}
|
665 |
+
|
666 |
+
function tvc_requiresLanguageInput( channel ) {
|
667 |
+
switch ( channel ) {
|
668 |
+
case '26':
|
669 |
+
return true; // Galaxus Product Data
|
670 |
+
|
671 |
+
default:
|
672 |
+
return false;
|
673 |
+
}
|
674 |
+
}
|
675 |
+
|
676 |
+
/**
|
677 |
+
* returns if a channel is a custom feed channel
|
678 |
+
*
|
679 |
+
* @param {string} channel
|
680 |
+
* @returns {boolean}
|
681 |
+
*/
|
682 |
+
function tvc_isCustomChannel( channel ) {
|
683 |
+
switch ( channel ) {
|
684 |
+
case '996': // Custom TSV Feed
|
685 |
+
case '997': // Custom TXT Feed
|
686 |
+
case '998': // Custom CSV Feed
|
687 |
+
case '999': // Custom XML Feed
|
688 |
+
return true;
|
689 |
+
|
690 |
+
default:
|
691 |
+
return false;
|
692 |
+
}
|
693 |
+
}
|
694 |
+
|
695 |
+
// ALERT! has a php equivalent in class-feed-master.php called set_attribute_status();
|
696 |
+
function setAttributeStatus( fieldLevel, fieldValue ) {
|
697 |
+
if ( fieldLevel > 0 && fieldLevel < 3 ) {
|
698 |
+
return true;
|
699 |
+
}
|
700 |
+
|
701 |
+
if ( fieldValue ) {
|
702 |
+
return true;
|
703 |
+
}
|
704 |
+
|
705 |
+
return false;
|
706 |
+
}
|
707 |
+
|
includes/application/js/tvc_channel-functions.min.js
ADDED
@@ -0,0 +1,498 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
function tvc_showChannelInputs(b, a) {
|
2 |
+
var c = {
|
3 |
+
"1": "switchToGoogleFeedFormMainInputs",
|
4 |
+
"2": "switchToBingFeedFormMainInputs",
|
5 |
+
"3": "switchToBeslisFeedFormMainInputs",
|
6 |
+
"4": "switchToPricegrabberFeedFormMainInputs",
|
7 |
+
"5": "switchToShoppingFeedFormMainInputs",
|
8 |
+
"6": "switchToAmazonFeedFormMainInputs",
|
9 |
+
"7": "switchToConnexityFeedFormMainInputs",
|
10 |
+
"9": "switchToNextagFeedFormMainInputs",
|
11 |
+
"10": "switchToKieskeurigFeedFormMainInputs",
|
12 |
+
"11": "switchToVergelijkFeedFormMainInputs",
|
13 |
+
"12": "switchToKoopjespakkerFeedFormMainInputs",
|
14 |
+
"13": "switchToAvantLinkFeedFormMainInputs",
|
15 |
+
"14": "switchToZboziFeedFormMainInputs",
|
16 |
+
"15": "switchToComconFeedFormMainInputs",
|
17 |
+
"16": "switchToFacebookFeedFormMainInputs",
|
18 |
+
"17": "switchToBolFeedFormMainInputs",
|
19 |
+
"18": "switchToAdtractionFeedFormMainInputs",
|
20 |
+
"19": "switchToRicardoFeedFormMainInputs",
|
21 |
+
"20": "switchToEbayFeedFormMainInputs",
|
22 |
+
"21": "switchToShopzillaFeedFormMainInputs",
|
23 |
+
"22": "switchToConvertoFeedFormMainInputs",
|
24 |
+
"23": "switchToIdealoFeedFormMainInputs",
|
25 |
+
"24": "switchToHeurekaFeedFormMainInputs",
|
26 |
+
"25": "switchToPepperjamFeedFormMainInputs",
|
27 |
+
"26": "switchToGalaxusProductDataFeedFormMainInputs",
|
28 |
+
"27": "switchToGalaxusProductPropertiesFeedFormMainInputs",
|
29 |
+
"28": "switchToGalaxusProductStockPricingFeedFormMainInputs",
|
30 |
+
"996": "switchToTsvFeedFormMainInputs",
|
31 |
+
"997": "switchToTxtFeedFormMainInputs",
|
32 |
+
"998": "switchToCsvFeedFormMainInputs",
|
33 |
+
"999": "switchToFeedFormMainInputs"
|
34 |
+
};
|
35 |
+
if (c.hasOwnProperty(b)) {
|
36 |
+
window[c[b]](a, b)
|
37 |
+
}
|
38 |
+
jQuery("#update-schedule-row").show();
|
39 |
+
jQuery("#add-product-variations-row").show();
|
40 |
+
if ((null === jQuery("#lvl_0").val() && "" === jQuery("#selected-categories").html()) || 0 === jQuery("#tvc-countries-selector").val()) {
|
41 |
+
tvc_show_or_hide_category_map(b)
|
42 |
+
} else {
|
43 |
+
jQuery("#tvc-category-map").show()
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
function tvc_show_or_hide_category_map(b) {
|
48 |
+
var a = jQuery("#tvc-category-map");
|
49 |
+
switch (b) {
|
50 |
+
case"15":
|
51 |
+
case"17":
|
52 |
+
case"18":
|
53 |
+
case"22":
|
54 |
+
case"23":
|
55 |
+
case"25":
|
56 |
+
case"26":
|
57 |
+
case"27":
|
58 |
+
case"28":
|
59 |
+
a.show();
|
60 |
+
break;
|
61 |
+
default:
|
62 |
+
a.hide();
|
63 |
+
break
|
64 |
+
}
|
65 |
+
}
|
66 |
+
|
67 |
+
function tvc_category_separator(a) {
|
68 |
+
switch (a) {
|
69 |
+
case"14":
|
70 |
+
case"24":
|
71 |
+
return " | ";
|
72 |
+
default:
|
73 |
+
return " > "
|
74 |
+
}
|
75 |
+
}
|
76 |
+
|
77 |
+
function tvc_reactOnChannelInputChanged(d, b, g) {
|
78 |
+
var f = "";
|
79 |
+
var c = tvc_getUrlVariable("tab");
|
80 |
+
if ("product-feed" === c) {
|
81 |
+
var e = {
|
82 |
+
"1": "googleInputChanged",
|
83 |
+
"2": "bingInputChanged",
|
84 |
+
"3": "beslisInputChanged",
|
85 |
+
"4": "pricegrabberInputChanged",
|
86 |
+
"5": "shoppingInputChanged",
|
87 |
+
"6": "amazonInputChanged",
|
88 |
+
"7": "connexityInputChanged",
|
89 |
+
"9": "nextagInputChanged",
|
90 |
+
"10": "kieskeurigInputChanged",
|
91 |
+
"11": "vergelijkInputChanged",
|
92 |
+
"12": "koopjespakkerInputChanged",
|
93 |
+
"13": "avantlinkInputChanged",
|
94 |
+
"14": "zboziInputChanged",
|
95 |
+
"15": "comconInputChanged",
|
96 |
+
"16": "facebookInputChanged",
|
97 |
+
"17": "bolInputChanged",
|
98 |
+
"18": "adtractionInputChanged",
|
99 |
+
"19": "ricardoInputChanged",
|
100 |
+
"20": "ebayInputChanged",
|
101 |
+
"21": "shopzillaInputChanged",
|
102 |
+
"22": "convertoInputChanged",
|
103 |
+
"23": "idealoInputChanged",
|
104 |
+
"24": "heurekaInputChanged",
|
105 |
+
"25": "pepperjamInputChanged",
|
106 |
+
"26": "galaxusProductDataInputChanged",
|
107 |
+
"27": "galaxusProductStockPricingInputChanged",
|
108 |
+
"28": "galaxusProductPropertiesInputChanged",
|
109 |
+
"996": "TsvInputChanged",
|
110 |
+
"997": "TxtInputChanged",
|
111 |
+
"998": "CsvInputChanged",
|
112 |
+
"999": "InputChanged"
|
113 |
+
};
|
114 |
+
f = e[d]
|
115 |
+
} else {
|
116 |
+
var a = tvc_convertToCamelCase(c.split("-"));
|
117 |
+
f = a + "Changed"
|
118 |
+
}
|
119 |
+
if (f) {
|
120 |
+
window[f](b, g)
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
124 |
+
function tvc_getChannelFeedType(a) {
|
125 |
+
switch (a) {
|
126 |
+
case"2":
|
127 |
+
case"4":
|
128 |
+
case"6":
|
129 |
+
case"7":
|
130 |
+
case"9":
|
131 |
+
case"12":
|
132 |
+
case"21":
|
133 |
+
case"25":
|
134 |
+
case"997":
|
135 |
+
return "txt";
|
136 |
+
case"15":
|
137 |
+
case"17":
|
138 |
+
case"19":
|
139 |
+
case"22":
|
140 |
+
case"23":
|
141 |
+
case"26":
|
142 |
+
case"27":
|
143 |
+
case"28":
|
144 |
+
case"998":
|
145 |
+
return "csv";
|
146 |
+
case"996":
|
147 |
+
return "tsv";
|
148 |
+
default:
|
149 |
+
return "xml"
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
function tvc_channelCountryCode(a) {
|
154 |
+
var b = "en-US";
|
155 |
+
switch (a) {
|
156 |
+
case"3":
|
157 |
+
case"10":
|
158 |
+
case"11":
|
159 |
+
case"12":
|
160 |
+
case"17":
|
161 |
+
b = "nl-NL";
|
162 |
+
break;
|
163 |
+
case"14":
|
164 |
+
case"24":
|
165 |
+
b = "cs-CZ";
|
166 |
+
break;
|
167 |
+
case"19":
|
168 |
+
b = "de-CH";
|
169 |
+
break;
|
170 |
+
case"23":
|
171 |
+
b = "de-DE";
|
172 |
+
break
|
173 |
+
}
|
174 |
+
return b
|
175 |
+
}
|
176 |
+
|
177 |
+
function tvc_channelUsesOwnCategories(a) {
|
178 |
+
switch (a) {
|
179 |
+
case"10":
|
180 |
+
case"15":
|
181 |
+
case"17":
|
182 |
+
case"18":
|
183 |
+
case"22":
|
184 |
+
case"23":
|
185 |
+
case"25":
|
186 |
+
case"26":
|
187 |
+
case"27":
|
188 |
+
case"28":
|
189 |
+
return true;
|
190 |
+
default:
|
191 |
+
return false
|
192 |
+
}
|
193 |
+
}
|
194 |
+
|
195 |
+
function tvc_fillCategoryVariables(b, d, a) {
|
196 |
+
var c = {
|
197 |
+
"1": "fillGoogleCategoryVariables",
|
198 |
+
"4": "fillPricegrabberCategoryVariables",
|
199 |
+
"5": "fillShoppingCategoryVariables",
|
200 |
+
"6": "fillAmazonCategoryVariables",
|
201 |
+
"7": "fillConnexityCategoryVariables",
|
202 |
+
"9": "fillNextagCategoryVariables",
|
203 |
+
"13": "fillAvantLinkCategoryVariables",
|
204 |
+
"14": "fillZboziCategoryVariables"
|
205 |
+
};
|
206 |
+
if (c.hasOwnProperty(b)) {
|
207 |
+
window[c[b]](d, a)
|
208 |
+
}
|
209 |
+
}
|
210 |
+
|
211 |
+
function tvc_displayCorrectStaticField(f, e, g, d, h, c) {
|
212 |
+
var b = "";
|
213 |
+
var a = tvc_restrictedStaticFields(d, h);
|
214 |
+
if (a !== undefined) {
|
215 |
+
if (a.length === 0) {
|
216 |
+
b = tvc_staticInputField(f, e, g, c)
|
217 |
+
} else {
|
218 |
+
b = tvc_staticInputSelect(f, e, g, a, c)
|
219 |
+
}
|
220 |
+
}
|
221 |
+
return b
|
222 |
+
}
|
223 |
+
|
224 |
+
function tvc_getAdvisedInputs(a) {
|
225 |
+
var b = {
|
226 |
+
"1": "woocommerceToGoogleFields",
|
227 |
+
"2": "woocommerceToBingFields",
|
228 |
+
"3": "woocommerceToBeslisFields",
|
229 |
+
"4": "woocommerceToPricegrabberFields",
|
230 |
+
"5": "woocommerceToShoppingFields",
|
231 |
+
"6": "woocommerceToAmazonFields",
|
232 |
+
"7": "woocommerceToConnexityFields",
|
233 |
+
"9": "woocommerceToNextagFields",
|
234 |
+
"10": "woocommerceToKieskeurigFields",
|
235 |
+
"11": "woocommerceToVergelijkFields",
|
236 |
+
"12": "woocommerceToKoopjespakkerFields",
|
237 |
+
"13": "woocommerceToAvantLinkFields",
|
238 |
+
"14": "woocommerceToZboziFields",
|
239 |
+
"15": "woocommerceToComconFields",
|
240 |
+
"16": "woocommerceToFacebookFields",
|
241 |
+
"17": "woocommerceToBolFields",
|
242 |
+
"18": "woocommerceToAdtractionFields",
|
243 |
+
"19": "woocommerceToRicardoFields",
|
244 |
+
"20": "woocommerceToeBayFields",
|
245 |
+
"21": "woocommerceToShopzillaFields",
|
246 |
+
"22": "woocommerceToConvertoFields",
|
247 |
+
"23": "woocommerceToIdealoFields",
|
248 |
+
"24": "woocommerceToHeurekaFields",
|
249 |
+
"25": "woocommerceToPepperjamFields",
|
250 |
+
"26": "woocommerceToGalaxusProductDataFields",
|
251 |
+
"27": "woocommerceToGalaxusProductStockPricingFields",
|
252 |
+
"28": "woocommerceToGalaxusProductPropertiesFields"
|
253 |
+
};
|
254 |
+
if (b.hasOwnProperty(a)) {
|
255 |
+
return window[b[a]]()
|
256 |
+
} else {
|
257 |
+
return []
|
258 |
+
}
|
259 |
+
}
|
260 |
+
|
261 |
+
function tvc_setOutputAttributeLevels(b, c, a) {
|
262 |
+
switch (b) {
|
263 |
+
case"1":
|
264 |
+
return setGoogleOutputAttributeLevels(c, a);
|
265 |
+
case"2":
|
266 |
+
return setBingOutputAttributeLevels(c);
|
267 |
+
case"3":
|
268 |
+
return setBeslisOutputAttributeLevels(c);
|
269 |
+
case"4":
|
270 |
+
return setPricegrabberOutputAttributeLevels(c);
|
271 |
+
case"5":
|
272 |
+
return setShoppingOutputAttributeLevels(c);
|
273 |
+
case"6":
|
274 |
+
return setAmazonOutputAttributeLevels(c);
|
275 |
+
case"7":
|
276 |
+
return setConnexityOutputAttributeLevels(c);
|
277 |
+
case"9":
|
278 |
+
return setNextagOutputAttributeLevels(c);
|
279 |
+
case"10":
|
280 |
+
return setKieskeurigOutputAttributeLevels(c);
|
281 |
+
case"11":
|
282 |
+
return setVergelijkOutputAttributeLevels(c);
|
283 |
+
case"13":
|
284 |
+
return setAvantLinkOutputAttributeLevels(c, a);
|
285 |
+
case"14":
|
286 |
+
return setZboziOutputAttributeLevels(c, a);
|
287 |
+
case"26":
|
288 |
+
return setGalaxusProductDataAttributeLevels(c, a);
|
289 |
+
case"27":
|
290 |
+
return setGalaxusProductStockPricingAttributeLevels(c);
|
291 |
+
case"28":
|
292 |
+
return setGalaxusProductPropertiesAttributeLevels(c);
|
293 |
+
case"996":
|
294 |
+
return setTsvOutputAttributeLevels(c);
|
295 |
+
case"997":
|
296 |
+
return setTxtOutputAttributeLevels(c);
|
297 |
+
case"998":
|
298 |
+
return setCsvOutputAttributeLevels(c);
|
299 |
+
case"999":
|
300 |
+
return setOutputAttributeLevels(c);
|
301 |
+
default:
|
302 |
+
return c
|
303 |
+
}
|
304 |
+
}
|
305 |
+
|
306 |
+
function tvc_restrictedStaticFields(a, c) {
|
307 |
+
var b = {
|
308 |
+
"1": "googleStaticFieldOptions",
|
309 |
+
"2": "bingStaticFieldOptions",
|
310 |
+
"3": "beslisStaticFieldOptions",
|
311 |
+
"4": "pricegrabberStaticFieldOptions",
|
312 |
+
"5": "shoppingStaticFieldOptions",
|
313 |
+
"6": "amazonStaticFieldOptions",
|
314 |
+
"7": "connexityStaticFieldOptions",
|
315 |
+
"9": "nextagStaticFieldOptions",
|
316 |
+
"10": "kieskeurigStaticFieldOptions",
|
317 |
+
"11": "vergelijkStaticFieldOptions",
|
318 |
+
"12": "koopjespakkerStaticFieldOptions",
|
319 |
+
"13": "avantlinkStaticFieldOptions",
|
320 |
+
"14": "zboziStaticFieldOptions",
|
321 |
+
"15": "comconStaticFieldOptions",
|
322 |
+
"16": "facebookStaticFieldOptions",
|
323 |
+
"17": "bolStaticFieldOptions",
|
324 |
+
"18": "adtractionStaticFieldOptions",
|
325 |
+
"19": "ricardoStaticFieldOptions",
|
326 |
+
"20": "ebayStaticFieldOptions",
|
327 |
+
"21": "shopzillaStaticFieldOptions",
|
328 |
+
"23": "idealoStaticFieldOptions",
|
329 |
+
"25": "pepperjamStaticFieldOptions",
|
330 |
+
"26": "galaxusProductDataStaticFieldOptions",
|
331 |
+
"27": "galaxusProductStockPricingStaticFieldOptions",
|
332 |
+
"28": "galaxusProductPropertiesStaticFieldOptions"
|
333 |
+
};
|
334 |
+
if (b.hasOwnProperty(a)) {
|
335 |
+
return window[b[a]](c)
|
336 |
+
} else {
|
337 |
+
return []
|
338 |
+
}
|
339 |
+
}
|
340 |
+
|
341 |
+
function tvc_setChannelRelatedPresets(a, b) {
|
342 |
+
switch (b) {
|
343 |
+
case"1":
|
344 |
+
if (a.field_label === "condition" || a.field_label === "availability" || a.field_label === "identifier_exists" || a.field_label === "adult" || a.field_label === "price") {
|
345 |
+
if (!a.value) {
|
346 |
+
a.value = setGooglePresets(a.field_label)
|
347 |
+
}
|
348 |
+
}
|
349 |
+
break;
|
350 |
+
case"2":
|
351 |
+
if (a.field_label === "seller_name") {
|
352 |
+
if (!a.value) {
|
353 |
+
a.value = setBingPresets(a.field_label)
|
354 |
+
}
|
355 |
+
}
|
356 |
+
break;
|
357 |
+
case"3":
|
358 |
+
if (a.field_label === "Conditie" || a.field_label === "Levertijd") {
|
359 |
+
if (!a.value) {
|
360 |
+
a.value = setBeslisPresets(a.field_label)
|
361 |
+
}
|
362 |
+
}
|
363 |
+
break;
|
364 |
+
case"13":
|
365 |
+
if (a.field_label === "condition" || a.field_label === "availability" || a.field_label === "identifier_exists") {
|
366 |
+
if (!a.value) {
|
367 |
+
a.value = setAvantLinkPresets(a.field_label)
|
368 |
+
}
|
369 |
+
}
|
370 |
+
break;
|
371 |
+
case"14":
|
372 |
+
if (a.field_label === "EROTIC" || a.field_label === "VISIBILITY") {
|
373 |
+
if (!a.value) {
|
374 |
+
a.value = setZboziPresets(a.field_label)
|
375 |
+
}
|
376 |
+
}
|
377 |
+
break;
|
378 |
+
case"15":
|
379 |
+
if (a.field_label === "Delivery time") {
|
380 |
+
if (!a.value) {
|
381 |
+
a.value = setComconPresets(a.field_label)
|
382 |
+
}
|
383 |
+
}
|
384 |
+
break;
|
385 |
+
case"16":
|
386 |
+
if (a.field_label === "condition" || a.field_label === "availability" || a.field_label === "price") {
|
387 |
+
if (!a.value) {
|
388 |
+
a.value = setFacebookPresets(a.field_label)
|
389 |
+
}
|
390 |
+
}
|
391 |
+
break;
|
392 |
+
case"17":
|
393 |
+
if (a.field_label === "Condition" || a.field_label === "Deliverycode") {
|
394 |
+
if (!a.value) {
|
395 |
+
a.value = setBolPresets(a.field_label)
|
396 |
+
}
|
397 |
+
}
|
398 |
+
break;
|
399 |
+
case"18":
|
400 |
+
if (a.field_label === "instock") {
|
401 |
+
if (!a.value) {
|
402 |
+
a.value = setAdtractionPresets(a.field_label)
|
403 |
+
}
|
404 |
+
}
|
405 |
+
break;
|
406 |
+
case"19":
|
407 |
+
if (a.field_label === "Descriptions[0].LanguageNr" || a.field_label === "Increment" || a.field_label === "AvailabilityId" || a.field_label === "Condition") {
|
408 |
+
if (!a.value) {
|
409 |
+
a.value = setRicardoPresets(a.field_label)
|
410 |
+
}
|
411 |
+
}
|
412 |
+
break;
|
413 |
+
case"20":
|
414 |
+
break;
|
415 |
+
case"21":
|
416 |
+
if (a.field_label === "Availability" || a.field_label === "Condition") {
|
417 |
+
if (!a.value) {
|
418 |
+
a.value = setShopzillaPresets(a.field_label)
|
419 |
+
}
|
420 |
+
}
|
421 |
+
break;
|
422 |
+
case"22":
|
423 |
+
if (a.field_label === "Availability" || a.field_label === "Condition") {
|
424 |
+
if (!a.value) {
|
425 |
+
a.value = setShopzillaPresets(a.field_label)
|
426 |
+
}
|
427 |
+
}
|
428 |
+
break;
|
429 |
+
case"24":
|
430 |
+
if ("ITEM_TYPE" === a.field_label) {
|
431 |
+
if (!a.value) {
|
432 |
+
a.value = setHeurekaPresets(a.field_label)
|
433 |
+
}
|
434 |
+
}
|
435 |
+
break;
|
436 |
+
case"25":
|
437 |
+
if ("ITEM_TYPE" === a.discontinued) {
|
438 |
+
if (!a.value) {
|
439 |
+
a.value = setPepperjamPresets(a.field_label)
|
440 |
+
}
|
441 |
+
}
|
442 |
+
break;
|
443 |
+
case"26":
|
444 |
+
if ("ITEM_TYPE" === a.discontinued) {
|
445 |
+
if (!a.value) {
|
446 |
+
a.value = setGalaxusProductDataPresets(a.field_label)
|
447 |
+
}
|
448 |
+
}
|
449 |
+
break;
|
450 |
+
case"27":
|
451 |
+
if ("ITEM_TYPE" === a.discontinued) {
|
452 |
+
if (!a.value) {
|
453 |
+
a.value = setGalaxusProductStockPricingPresets(a.field_label)
|
454 |
+
}
|
455 |
+
}
|
456 |
+
break;
|
457 |
+
case"28":
|
458 |
+
if ("ITEM_TYPE" === a.discontinued) {
|
459 |
+
if (!a.value) {
|
460 |
+
a.value = setGalaxusProductPropertiesPresets(a.field_label)
|
461 |
+
}
|
462 |
+
}
|
463 |
+
break;
|
464 |
+
default:
|
465 |
+
break
|
466 |
+
}
|
467 |
+
}
|
468 |
+
|
469 |
+
function tvc_requiresLanguageInput(a) {
|
470 |
+
switch (a) {
|
471 |
+
case"26":
|
472 |
+
return true;
|
473 |
+
default:
|
474 |
+
return false
|
475 |
+
}
|
476 |
+
}
|
477 |
+
|
478 |
+
function tvc_isCustomChannel(a) {
|
479 |
+
switch (a) {
|
480 |
+
case"996":
|
481 |
+
case"997":
|
482 |
+
case"998":
|
483 |
+
case"999":
|
484 |
+
return true;
|
485 |
+
default:
|
486 |
+
return false
|
487 |
+
}
|
488 |
+
}
|
489 |
+
|
490 |
+
function setAttributeStatus(b, a) {
|
491 |
+
if (b > 0 && b < 3) {
|
492 |
+
return true
|
493 |
+
}
|
494 |
+
if (a) {
|
495 |
+
return true
|
496 |
+
}
|
497 |
+
return false
|
498 |
+
};
|
includes/application/js/tvc_feedhandling.js
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"use strict";
|
2 |
+
var _feedHolder;
|
3 |
+
|
4 |
+
function tvc_getFeedAttributes( feedId, channel, callback ) {
|
5 |
+
tvc_getOutputFields(
|
6 |
+
feedId,
|
7 |
+
channel,
|
8 |
+
function( fields ) {
|
9 |
+
if ( fields !== '0' ) {
|
10 |
+
callback( JSON.parse( fields ) );
|
11 |
+
} else {
|
12 |
+
callback( [] ); // free feed format selected
|
13 |
+
}
|
14 |
+
}
|
15 |
+
);
|
16 |
+
}
|
17 |
+
|
18 |
+
function tvc_customSourceFields( sourceId, callback ) {
|
19 |
+
tvc_getSourceFields(
|
20 |
+
sourceId,
|
21 |
+
function( fields ) {
|
22 |
+
callback( fields && fields !== '0' ? JSON.parse( fields ) : '0' );
|
23 |
+
}
|
24 |
+
);
|
25 |
+
}
|
26 |
+
|
27 |
+
function tvc_mainFeedFilters( feedId, callback ) {
|
28 |
+
|
29 |
+
tvc_getMainFeedFilters(
|
30 |
+
feedId,
|
31 |
+
function( filters ) {
|
32 |
+
callback( filters !== '0' ? JSON.parse( filters ) : null );
|
33 |
+
}
|
34 |
+
);
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Fills the attributes of the current _feed object with data from the outputs var
|
39 |
+
*
|
40 |
+
* @param {array} outputs containing output strings outputs
|
41 |
+
* @param {string} channel id
|
42 |
+
* @param {int} source id
|
43 |
+
*/
|
44 |
+
function tvc_addFeedAttributes( outputs, channel, source ) {
|
45 |
+
|
46 |
+
var inputs = tvc_getAdvisedInputs( channel );
|
47 |
+
var i = 0;
|
48 |
+
|
49 |
+
_feedHolder.clearAllAttributes();
|
50 |
+
|
51 |
+
for ( var field in outputs ) {
|
52 |
+
|
53 |
+
var outputTitle = outputs[ field ][ 'field_label' ];
|
54 |
+
var activity = true;
|
55 |
+
|
56 |
+
/**
|
57 |
+
* deactivate if this attribute is not required and has no value
|
58 |
+
*/
|
59 |
+
if ( parseInt( outputs[ field ][ 'category_id' ] ) > 2 && outputs[ field ][ 'value' ] === '' ) {
|
60 |
+
activity = false;
|
61 |
+
} else if ( outputs[ field ][ 'category_id' ] === '0' ) {
|
62 |
+
activity = false;
|
63 |
+
} else if ( parseInt( outputs[ field ][ 'category_id' ] ) > 2 && outputs[ field ][ 'value' ] === undefined ) {
|
64 |
+
activity = false;
|
65 |
+
}
|
66 |
+
|
67 |
+
tvc_setChannelRelatedPresets( outputs[ field ], channel );
|
68 |
+
|
69 |
+
_feedHolder.addAttribute( i, outputTitle, inputs[ outputTitle ], outputs[ field ][ 'value' ], outputs[ field ][ 'category_id' ], activity, 0, 0, 0 );
|
70 |
+
|
71 |
+
i ++;
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
function tvc_saveFeedToDb( feed, callback ) {
|
76 |
+
|
77 |
+
/**
|
78 |
+
* store the feed in a local variable
|
79 |
+
*/
|
80 |
+
_feedHolder = feed;
|
81 |
+
|
82 |
+
var feedDataSelectorTable = jQuery( '#tvc-ajax-feed-data-to-database-conversion-array' ).text(); // get the data from the edit feed form code
|
83 |
+
var feedDataToStore = tvc_getFeedDataToStore( feedDataSelectorTable );
|
84 |
+
var metaToStore = tvc_filterActiveMetaData( _feedHolder[ 'attributes' ], _feedHolder[ 'categoryMapping' ] );
|
85 |
+
var feedFilter = _feedHolder[ 'feedFilter' ];
|
86 |
+
|
87 |
+
tvc_updateFeedToDb(
|
88 |
+
feedDataToStore,
|
89 |
+
metaToStore,
|
90 |
+
feedFilter,
|
91 |
+
function( response ) {
|
92 |
+
callback( response.trim() );
|
93 |
+
}
|
94 |
+
);
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Gets the full metaData array from the _feedHolder and returns a tvc_attributeMeta object with keys and values from only the active ones.
|
99 |
+
* Also stores the category mapping array in a tvc_attributeMeta object.
|
100 |
+
*
|
101 |
+
* @param {Array} metaData
|
102 |
+
* @param {Array} categoryMapping
|
103 |
+
* @returns {Array} array with tvc_attributeMeta objects containing meta keys and meta values
|
104 |
+
*/
|
105 |
+
function tvc_filterActiveMetaData( metaData, categoryMapping ) {
|
106 |
+
|
107 |
+
// make a storage place to store the changed attributes
|
108 |
+
var activeMeta = [];
|
109 |
+
|
110 |
+
for ( var i = 0; i < metaData.length; i ++ ) {
|
111 |
+
|
112 |
+
// if the advised source is not equal to the advised inputs, the user has selected his own input so this needs to be stored
|
113 |
+
if ( metaData[ i ][ 'value' ] !== undefined && metaData[ i ][ 'value' ] !== '' && metaData[ i ][ 'isActive' ] === true ) {
|
114 |
+
|
115 |
+
// store the meta data in a Tvc_AttributeMeta object
|
116 |
+
activeMeta.push( new Tvc_AttributeMeta( metaData[ i ][ 'fieldName' ], metaData[ i ][ 'value' ] ) );
|
117 |
+
}
|
118 |
+
}
|
119 |
+
|
120 |
+
// also store the category mapping as meta data
|
121 |
+
if ( categoryMapping.length > 0 ) {
|
122 |
+
|
123 |
+
activeMeta.push( new Tvc_AttributeMeta( 'category_mapping', categoryMapping ) );
|
124 |
+
}
|
125 |
+
|
126 |
+
return activeMeta;
|
127 |
+
}
|
128 |
+
|
129 |
+
function tvc_getFeedDataToStore( feedDataSelector ) {
|
130 |
+
var selector = JSON.parse( feedDataSelector );
|
131 |
+
var result = [];
|
132 |
+
|
133 |
+
for (var i = 0; i < selector.length; i++) {
|
134 |
+
var dataItem = {
|
135 |
+
'name' : selector[i]['db'],
|
136 |
+
'value' : undefined !== _feedHolder[ selector[i]['feed'] ] ? _feedHolder[ selector[i]['feed'] ] : '',
|
137 |
+
'type' : selector[i]['type']
|
138 |
+
};
|
139 |
+
|
140 |
+
result.push( dataItem );
|
141 |
+
}
|
142 |
+
|
143 |
+
return result;
|
144 |
+
}
|
includes/application/js/tvc_feedhandling.min.js
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
var _feedHolder;
|
2 |
+
|
3 |
+
function tvc_getFeedAttributes(a, b, c) {
|
4 |
+
tvc_getOutputFields(a, b, function (d) {
|
5 |
+
if (d !== "0") {
|
6 |
+
c(JSON.parse(d))
|
7 |
+
} else {
|
8 |
+
c([])
|
9 |
+
}
|
10 |
+
})
|
11 |
+
}
|
12 |
+
|
13 |
+
function tvc_customSourceFields(a, b) {
|
14 |
+
tvc_getSourceFields(a, function (c) {
|
15 |
+
b(c && c !== "0" ? JSON.parse(c) : "0")
|
16 |
+
})
|
17 |
+
}
|
18 |
+
|
19 |
+
function tvc_mainFeedFilters(a, b) {
|
20 |
+
tvc_getMainFeedFilters(a, function (c) {
|
21 |
+
b(c !== "0" ? JSON.parse(c) : null)
|
22 |
+
})
|
23 |
+
}
|
24 |
+
|
25 |
+
function tvc_addFeedAttributes(h, d, e) {
|
26 |
+
var a = tvc_getAdvisedInputs(d);
|
27 |
+
var c = 0;
|
28 |
+
_feedHolder.clearAllAttributes();
|
29 |
+
for (var g in h) {
|
30 |
+
var b = h[g]["field_label"];
|
31 |
+
var f = true;
|
32 |
+
if (parseInt(h[g]["category_id"]) > 2 && h[g]["value"] === "") {
|
33 |
+
f = false
|
34 |
+
} else {
|
35 |
+
if (h[g]["category_id"] === "0") {
|
36 |
+
f = false
|
37 |
+
} else {
|
38 |
+
if (parseInt(h[g]["category_id"]) > 2 && h[g]["value"] === undefined) {
|
39 |
+
f = false
|
40 |
+
}
|
41 |
+
}
|
42 |
+
}
|
43 |
+
tvc_setChannelRelatedPresets(h[g], d);
|
44 |
+
_feedHolder.addAttribute(c, b, a[b], h[g]["value"], h[g]["category_id"], f, 0, 0, 0);
|
45 |
+
c++
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
function tvc_saveFeedToDb(d, f) {
|
50 |
+
_feedHolder = d;
|
51 |
+
var c = jQuery("#tvc-ajax-feed-data-to-database-conversion-array").text();
|
52 |
+
var a = tvc_getFeedDataToStore(c);
|
53 |
+
var b = tvc_filterActiveMetaData(_feedHolder.attributes, _feedHolder.categoryMapping);
|
54 |
+
var e = _feedHolder.feedFilter;
|
55 |
+
tvc_updateFeedToDb(a, b, e, function (g) {
|
56 |
+
f(g.trim())
|
57 |
+
})
|
58 |
+
}
|
59 |
+
|
60 |
+
function tvc_filterActiveMetaData(b, d) {
|
61 |
+
var a = [];
|
62 |
+
for (var c = 0; c < b.length; c++) {
|
63 |
+
if (b[c]["value"] !== undefined && b[c]["value"] !== "" && b[c]["isActive"] === true) {
|
64 |
+
a.push(new Tvc_AttributeMeta(b[c]["fieldName"], b[c]["value"]))
|
65 |
+
}
|
66 |
+
}
|
67 |
+
if (d.length > 0) {
|
68 |
+
a.push(new Tvc_AttributeMeta("category_mapping", d))
|
69 |
+
}
|
70 |
+
return a
|
71 |
+
}
|
72 |
+
|
73 |
+
function tvc_getFeedDataToStore(e) {
|
74 |
+
var b = JSON.parse(e);
|
75 |
+
var a = [];
|
76 |
+
for (var d = 0; d < b.length; d++) {
|
77 |
+
var c = {
|
78 |
+
name: b[d]["db"],
|
79 |
+
value: undefined !== _feedHolder[b[d]["feed"]] ? _feedHolder[b[d]["feed"]] : "",
|
80 |
+
type: b[d]["type"]
|
81 |
+
};
|
82 |
+
a.push(c)
|
83 |
+
}
|
84 |
+
return a
|
85 |
+
};
|
includes/application/js/tvc_general-functions.js
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"use strict";
|
2 |
+
/**
|
3 |
+
* Finds the index of an object with a specific value in an array of objects
|
4 |
+
*
|
5 |
+
* @param {array} theArray with objects
|
6 |
+
* @param {string} searchTerm
|
7 |
+
* @param {string} arrayProperty
|
8 |
+
* @returns {int} the index of the object or false of its not in the array
|
9 |
+
*/
|
10 |
+
function tvc_arrayObjectIndexOf( theArray, searchTerm, arrayProperty ) {
|
11 |
+
for ( var i = 0, len = theArray.length; i < len; i ++ ) {
|
12 |
+
if ( theArray[ i ][ arrayProperty ] === searchTerm ) {
|
13 |
+
return i; // return the index
|
14 |
+
}
|
15 |
+
}
|
16 |
+
|
17 |
+
return - 1; // return false if object could not be found
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Get a specific variable from the current url
|
22 |
+
*
|
23 |
+
* @param {string} key
|
24 |
+
* @returns {String}
|
25 |
+
*/
|
26 |
+
function tvc_getUrlVariable( key ) {
|
27 |
+
var result = '';
|
28 |
+
var url = window.location.search.substring( 1 );
|
29 |
+
var params = url.split( '&' );
|
30 |
+
|
31 |
+
for ( var i = 0; i < params.length; i ++ ) {
|
32 |
+
var param = params[ i ].split( '=' );
|
33 |
+
|
34 |
+
if ( param[ 0 ] === key ) {
|
35 |
+
result = param[ 1 ];
|
36 |
+
}
|
37 |
+
}
|
38 |
+
|
39 |
+
return result;
|
40 |
+
}
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Counts the number of items in an object
|
44 |
+
*
|
45 |
+
* @param {object} object
|
46 |
+
* @returns {int} number of items in object
|
47 |
+
*/
|
48 |
+
function tvc_countObjectItems( object ) {
|
49 |
+
var count = 0;
|
50 |
+
|
51 |
+
for ( var k in object ) {
|
52 |
+
if ( object.hasOwnProperty( k ) ) {
|
53 |
+
count ++;
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
return count;
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Returns true if the object is empty
|
62 |
+
*
|
63 |
+
* @param {object} object
|
64 |
+
* @returns {Boolean} true if object is empty
|
65 |
+
*/
|
66 |
+
// TODO: Er bestaat ook een jQuery.isEmptyObject() functie. In hoeverre is die bruikbaar ter vervanging van onderstaande functie?
|
67 |
+
function tvc_isEmptyQueryObject( object ) {
|
68 |
+
// null and undefined are "empty"
|
69 |
+
if ( object === null ) {
|
70 |
+
return true;
|
71 |
+
}
|
72 |
+
|
73 |
+
// Assume if it has a length property with a non-zero value
|
74 |
+
// that that property is correct.
|
75 |
+
if ( object.length > 0 ) {
|
76 |
+
return false;
|
77 |
+
}
|
78 |
+
if ( object.length === 0 ) {
|
79 |
+
return true;
|
80 |
+
}
|
81 |
+
|
82 |
+
// Otherwise, does it have any properties of its own?
|
83 |
+
// Note that this doesn't handle
|
84 |
+
// toString and valueOf enumeration bugs in IE < 9
|
85 |
+
for ( var key in object ) {
|
86 |
+
//if ( hasOwnProperty.call( object, key ) )
|
87 |
+
if ( object.hasOwnProperty( key ) ) {
|
88 |
+
return false;
|
89 |
+
}
|
90 |
+
}
|
91 |
+
return true;
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Takes a string with a number at the end and increments the number
|
96 |
+
*
|
97 |
+
* @param {String} stringWithNumber
|
98 |
+
* @returns {String} with incremented number
|
99 |
+
*/
|
100 |
+
function tvc_incrementLast( stringWithNumber ) {
|
101 |
+
return stringWithNumber.replace( /[0-9]+(?!.*[0-9])/, parseInt( stringWithNumber.match( /[0-9]+(?!.*[0-9])/ ), 10 ) + 1 );
|
102 |
+
}
|
includes/application/js/tvc_general-functions.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
function tvc_arrayObjectIndexOf(d,c,b){for(var e=0,a=d.length;e<a;e++){if(d[e][b]===c){return e}}return -1}function tvc_getUrlVariable(d){var a="";var b=window.location.search.substring(1);var f=b.split("&");for(var c=0;c<f.length;c++){var e=f[c].split("=");if(e[0]===d){a=e[1]}}return a}function tvc_countObjectItems(b){var c=0;for(var a in b){if(b.hasOwnProperty(a)){c++}}return c}function tvc_isEmptyQueryObject(a){if(a===null){return true}if(a.length>0){return false}if(a.length===0){return true}for(var b in a){if(a.hasOwnProperty(b)){return false}}return true}function tvc_incrementLast(a){return a.replace(/[0-9]+(?!.*[0-9])/,parseInt(a.match(/[0-9]+(?!.*[0-9])/),10)+1)};
|
includes/application/js/tvc_logic.js
ADDED
@@ -0,0 +1,454 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
"use strict";
|
3 |
+
/*global tvc_feed_settings_form_vars, tvc_manage_channels_vars, tvc_feed_list_form_vars */
|
4 |
+
var _feedHolder;
|
5 |
+
|
6 |
+
function tvc_editCategories() {
|
7 |
+
var cat_lvl_selector = jQuery( '#category-selector-lvl' );
|
8 |
+
|
9 |
+
if ( ! tvc_isCustomChannel( _feedHolder[ 'channel' ] ) ) {
|
10 |
+
var currentCategories = _feedHolder[ 'mainCategory' ].split( ' > ' );
|
11 |
+
var cat_length = currentCategories.length;
|
12 |
+
var cat_selectors = jQuery( '#lvl_' + ( cat_length ) ).html() !== '' ? cat_length + 1 : cat_length;
|
13 |
+
|
14 |
+
jQuery( '#selected-categories' ).hide();
|
15 |
+
jQuery( '#lvl_0' ).prop( 'disabled', false );
|
16 |
+
|
17 |
+
for ( var i = 0; i < cat_selectors; i ++ ) {
|
18 |
+
var levelElement = jQuery( '#lvl_' + i );
|
19 |
+
|
20 |
+
if ( ! currentCategories[ i ] ) {
|
21 |
+
levelElement.val( '0' );
|
22 |
+
}
|
23 |
+
levelElement.show();
|
24 |
+
}
|
25 |
+
} else {
|
26 |
+
// as the user selected a free format, just show a text input control
|
27 |
+
cat_lvl_selector.html(
|
28 |
+
tvc_freeCategoryInputCntrl(
|
29 |
+
'default',
|
30 |
+
_feedHolder[ 'feedId' ],
|
31 |
+
_feedHolder[ 'mainCategory' ]
|
32 |
+
)
|
33 |
+
);
|
34 |
+
cat_lvl_selector.prop( 'disabled', false );
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
function tvc_generateFeed() {
|
39 |
+
if ( jQuery( '#file-name' ).val() !== '' ) {
|
40 |
+
if ( _feedHolder[ 'categoryMapping' ] && _feedHolder[ 'categoryMapping' ].length > 0 ) {
|
41 |
+
disableFeedActionButtons();
|
42 |
+
tvc_generateAndSaveFeed();
|
43 |
+
} else {
|
44 |
+
var userInput = confirm(
|
45 |
+
tvc_feed_settings_form_vars.no_category_selected
|
46 |
+
);
|
47 |
+
|
48 |
+
if ( userInput === true ) {
|
49 |
+
disableFeedActionButtons();
|
50 |
+
tvc_generateAndSaveFeed();
|
51 |
+
}
|
52 |
+
}
|
53 |
+
} else {
|
54 |
+
jQuery( '#alert-message' ).
|
55 |
+
html( '<p>' + tvc_feed_settings_form_vars.file_name_required + '</p>' );
|
56 |
+
jQuery( '#success-message' ).show();
|
57 |
+
}
|
58 |
+
}
|
59 |
+
|
60 |
+
function tvc_saveFeedData() {
|
61 |
+
if ( jQuery( '#file-name' ).val() !== '' ) {
|
62 |
+
tvc_saveFeed();
|
63 |
+
} else {
|
64 |
+
jQuery( '#alert-message' ).
|
65 |
+
html( '<p>' + tvc_feed_settings_form_vars.file_name_required + '</p>' );
|
66 |
+
jQuery( '#success-message' ).show();
|
67 |
+
}
|
68 |
+
}
|
69 |
+
|
70 |
+
function getCombinedValue( rowId, sourceLevel ) {
|
71 |
+
var c = 1;
|
72 |
+
var combinedValue = '';
|
73 |
+
var oldValue = _feedHolder.getCombinedOutputValue( rowId, sourceLevel );
|
74 |
+
|
75 |
+
while ( jQuery( '#combined-input-field-cntrl-' + rowId + '-' + sourceLevel + '-' + c ).
|
76 |
+
val() ) {
|
77 |
+
var idString = rowId + '-' + sourceLevel + '-' + c;
|
78 |
+
|
79 |
+
var selectedValue = jQuery( '#combined-input-field-cntrl-' + idString ).
|
80 |
+
val();
|
81 |
+
|
82 |
+
combinedValue += c > 1 ?
|
83 |
+
jQuery( '#combined-separator-cntrl-' + idString ).val() + '#' :
|
84 |
+
'';
|
85 |
+
|
86 |
+
if ( selectedValue !== 'static' ) {
|
87 |
+
combinedValue += selectedValue !== 'select' ?
|
88 |
+
selectedValue + '|' :
|
89 |
+
'';
|
90 |
+
} else if ( jQuery( '#static-input-field-' + idString ).val() ) {
|
91 |
+
combinedValue += selectedValue + '#' + jQuery( '#static-input-field-' + idString ).val() + '|';
|
92 |
+
} else {
|
93 |
+
combinedValue = oldValue + '|';
|
94 |
+
break; // if one of the static input fields is still empty, return the old value
|
95 |
+
}
|
96 |
+
|
97 |
+
c ++;
|
98 |
+
}
|
99 |
+
|
100 |
+
combinedValue = combinedValue.substring( 0, combinedValue.length - 1 ); // remove the last |
|
101 |
+
|
102 |
+
return c > 1 ? combinedValue : false; // need at least two fields to be valid
|
103 |
+
}
|
104 |
+
|
105 |
+
function tvc_staticValueChanged( id, level, combinationLevel ) {
|
106 |
+
if ( combinationLevel > 0 ) { // the static field resides in a combination source
|
107 |
+
tvc_changedCombinedOutput( id, level, combinationLevel );
|
108 |
+
} else {
|
109 |
+
// store the change in the feed
|
110 |
+
tvc_setStaticValue( id, level, combinationLevel );
|
111 |
+
|
112 |
+
// when the identifier_exists static value has changed, the level of a few attributes should be changed
|
113 |
+
if ( id === 34 ) {
|
114 |
+
tvc_setIdentifierExistsDependancies();
|
115 |
+
}
|
116 |
+
}
|
117 |
+
}
|
118 |
+
|
119 |
+
function tvc_changedOutputSelection( level ) {
|
120 |
+
var outputFieldControlElement = jQuery( '#output-field-cntrl-' + level );
|
121 |
+
|
122 |
+
if ( outputFieldControlElement.val() !== 'no-value' ) {
|
123 |
+
tvc_activateOptionalFieldRow( level, outputFieldControlElement.val() );
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
function tvc_hasExtraSourceRow( nrOfSources, value ) {
|
128 |
+
if ( value.length > 0 ) {
|
129 |
+
return value[ nrOfSources - 1 ].hasOwnProperty( 'c' );
|
130 |
+
} else {
|
131 |
+
return false;
|
132 |
+
}
|
133 |
+
}
|
134 |
+
|
135 |
+
function tvc_changedCustomOutputTitle() {
|
136 |
+
var title = jQuery( '#custom-output-title-input' ).val();
|
137 |
+
|
138 |
+
if ( title ) {
|
139 |
+
tvc_activateCustomFieldRow( title );
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
function tvc_deleteSpecificFeed( id, title ) {
|
144 |
+
var userInput = confirm( tvc_feed_list_form_vars.confirm_delete_feed.replace( '%feedname%', title ) );
|
145 |
+
|
146 |
+
if ( userInput === true ) {
|
147 |
+
tvc_deleteFeed( id, title );
|
148 |
+
console.log( 'File ' + title + ' removed from server.' );
|
149 |
+
tvc_show_success_message( tvc_feed_list_form_vars.feed_removed.replace( '%feedname%', title ) );
|
150 |
+
parent.location='admin.php?page=tvc-product-feed-manager&tab=feed-list';
|
151 |
+
}
|
152 |
+
}
|
153 |
+
|
154 |
+
function tvc_alertRemoveChannel() {
|
155 |
+
var userInput = confirm( tvc_manage_channels_vars.confirm_removing_channel );
|
156 |
+
if ( true !== userInput ) {
|
157 |
+
return false;
|
158 |
+
}
|
159 |
+
}
|
160 |
+
|
161 |
+
function tvc_valueOptionChanged( rowId, sourceLevel, valueEditorLevel ) {
|
162 |
+
var type = jQuery( '#value-options-' + rowId + '-' + sourceLevel + '-' + valueEditorLevel ).val();
|
163 |
+
|
164 |
+
//var selectorCode = tvc_getCorrectValueSelector( rowId, sourceLevel, valueEditorLevel, type, '', '' );
|
165 |
+
var selectorCode = tvc_getCorrectValueSelector( rowId, sourceLevel, 0, type, '', '' );
|
166 |
+
|
167 |
+
jQuery( '#value-editor-input-span-' + rowId + '-' + sourceLevel + '-' + valueEditorLevel ).html( selectorCode );
|
168 |
+
}
|
169 |
+
|
170 |
+
function tvc_getCorrectValueSelector(
|
171 |
+
rowId, sourceLevel, valueEditorLevel, type, value, endValue ) {
|
172 |
+
var selectorCode = '';
|
173 |
+
|
174 |
+
// TODO: the type is now based on the value and on the text. Should be only value as this makes it
|
175 |
+
// easier to work with different languages
|
176 |
+
switch ( type ) {
|
177 |
+
case '0':
|
178 |
+
case 'change nothing':
|
179 |
+
tvc_valueInputOptionsChanged( rowId, sourceLevel, valueEditorLevel ); // save the value in meta as there is no input field required
|
180 |
+
selectorCode = '';
|
181 |
+
break;
|
182 |
+
|
183 |
+
case '1':
|
184 |
+
case 'overwrite':
|
185 |
+
selectorCode = tvc_valueOptionsSingleInput( rowId, sourceLevel, valueEditorLevel, value );
|
186 |
+
break;
|
187 |
+
|
188 |
+
case '2':
|
189 |
+
case 'replace':
|
190 |
+
selectorCode = tvc_valueOptionsReplaceInput( rowId, sourceLevel, valueEditorLevel, value, endValue );
|
191 |
+
break;
|
192 |
+
|
193 |
+
case '3':
|
194 |
+
case 'remove':
|
195 |
+
case '4':
|
196 |
+
case 'add prefix':
|
197 |
+
case '5':
|
198 |
+
case 'add suffix':
|
199 |
+
selectorCode = tvc_valueOptionsSingleInputValue( rowId, sourceLevel, valueEditorLevel, value );
|
200 |
+
break;
|
201 |
+
|
202 |
+
case '6':
|
203 |
+
case 'recalculate':
|
204 |
+
selectorCode = tvc_valueOptionsRecalculate( rowId, sourceLevel, valueEditorLevel, value, endValue );
|
205 |
+
break;
|
206 |
+
|
207 |
+
case '7':
|
208 |
+
case 'convert to child-element':
|
209 |
+
selectorCode = tvc_valueOptionsElementInput( rowId, sourceLevel, valueEditorLevel, value );
|
210 |
+
break;
|
211 |
+
|
212 |
+
default:
|
213 |
+
selectorCode = tvc_valueOptionsSingleInput( rowId, sourceLevel, valueEditorLevel, value );
|
214 |
+
break;
|
215 |
+
}
|
216 |
+
|
217 |
+
return selectorCode;
|
218 |
+
}
|
219 |
+
|
220 |
+
function tvc_deactivateFeed( id ) {
|
221 |
+
tvc_switchFeedStatus(
|
222 |
+
id,
|
223 |
+
function( result ) {
|
224 |
+
tvc_updateFeedRowStatus( id, parseInt( result ) );
|
225 |
+
}
|
226 |
+
);
|
227 |
+
}
|
228 |
+
|
229 |
+
function tvc_duplicateFeed( id, feedName ) {
|
230 |
+
tvc_duplicateExistingFeed(
|
231 |
+
id,
|
232 |
+
function( result ) {
|
233 |
+
if ( result ) {
|
234 |
+
tvc_show_success_message( tvc_feed_list_form_vars.added_feed_copy.replace( '%feedname%', feedName ) );
|
235 |
+
}
|
236 |
+
}
|
237 |
+
);
|
238 |
+
}
|
239 |
+
|
240 |
+
function tvc_regenerateFeed( feedId ) {
|
241 |
+
// when there's already a feed processing, then the status should be "in queue", else status should set to "processing"
|
242 |
+
var feedStatus = tvcQueueStringIsEmpty() ? 3 : 4;
|
243 |
+
|
244 |
+
tvcAddToQueueString( feedId );
|
245 |
+
|
246 |
+
tvc_showFeedSpinner();
|
247 |
+
|
248 |
+
tvc_updateFeedRowStatus( feedId, feedStatus );
|
249 |
+
|
250 |
+
console.log( 'Started regenerating feed ' + feedId );
|
251 |
+
|
252 |
+
tvc_updateFeedFile( feedId, function( xmlResult ) {
|
253 |
+
|
254 |
+
tvc_hideFeedSpinner();
|
255 |
+
|
256 |
+
console.log(xmlResult);
|
257 |
+
|
258 |
+
// activate the feed list status checker to update the feed list when a status changes
|
259 |
+
var checkStatus = setInterval( function(){
|
260 |
+
tvc_getCurrentFeedStatus( feedId, function( statResult ) {
|
261 |
+
var data = JSON.parse( statResult );
|
262 |
+
if ('3' !== data[ 'status_id' ] && '4' !== data[ 'status_id' ]) {
|
263 |
+
console.log( data );
|
264 |
+
tvc_resetFeedStatus( data );
|
265 |
+
tvc_resetFeedList();
|
266 |
+
clearInterval( checkStatus );
|
267 |
+
tvcRemoveFromQueueString( feedId );
|
268 |
+
}
|
269 |
+
} );
|
270 |
+
}, 10000 );
|
271 |
+
})
|
272 |
+
}
|
273 |
+
|
274 |
+
function tvc_viewFeed( url ) {
|
275 |
+
if ( -1 !== url.indexOf( 'http' ) ) { // Filter out duplicate feeds that have not been generated yet.
|
276 |
+
window.open(url);
|
277 |
+
} else {
|
278 |
+
alert( tvc_feed_list_form_vars.feed_not_generated );
|
279 |
+
}
|
280 |
+
}
|
281 |
+
|
282 |
+
function tvc_addRowValueEditor(
|
283 |
+
rowId, sourceLevel, valueEditorLevel, values ) {
|
284 |
+
// add the change values controls
|
285 |
+
jQuery( '#end-row-id-' + rowId ).remove();
|
286 |
+
jQuery( '#row-' + rowId ).
|
287 |
+
append( tvc_valueEditor( rowId, sourceLevel, valueEditorLevel, values ) + tvc_endrow( rowId ) );
|
288 |
+
|
289 |
+
// and remove the edit values control
|
290 |
+
jQuery( '#value-editor-input-query-add-span-' + rowId + '-' + sourceLevel + '-' + valueEditorLevel ).remove();
|
291 |
+
}
|
292 |
+
|
293 |
+
/**
|
294 |
+
* Takes an array of words and puts them together in a camel structure way.
|
295 |
+
*
|
296 |
+
* @param {array} stringArray contains the words from which the string should be generated
|
297 |
+
*
|
298 |
+
* @returns {string} camel structured string
|
299 |
+
*/
|
300 |
+
function tvc_convertToCamelCase( stringArray ) {
|
301 |
+
// first word should remain lowercase
|
302 |
+
var result = stringArray[ 0 ].toLowerCase();
|
303 |
+
|
304 |
+
for ( var i = 1; i < stringArray.length; i++ ) {
|
305 |
+
result += stringArray[ i ].charAt( 0 ).toUpperCase() + stringArray[ i ].slice( 1 );
|
306 |
+
}
|
307 |
+
|
308 |
+
return result;
|
309 |
+
}
|
310 |
+
|
311 |
+
function tvc_addValueEditorQuery( rowId, sourceLevel, conditionLevel ) {
|
312 |
+
if ( tvc_changeValueIsFilled( rowId, sourceLevel, conditionLevel ) ) {
|
313 |
+
if ( tvc_queryIsFilled(
|
314 |
+
rowId,
|
315 |
+
(
|
316 |
+
sourceLevel - 1
|
317 |
+
),
|
318 |
+
1
|
319 |
+
)
|
320 |
+
) {
|
321 |
+
tvc_showEditValueQuery( rowId, sourceLevel, conditionLevel, true );
|
322 |
+
} else {
|
323 |
+
alert( tvc_feed_settings_form_vars.query_requirements );
|
324 |
+
}
|
325 |
+
} else {
|
326 |
+
alert( tvc_feed_settings_form_vars.first_fill_in_change_value );
|
327 |
+
}
|
328 |
+
}
|
329 |
+
|
330 |
+
function tvc_queryStringToQueryObject( queryString ) {
|
331 |
+
var queryObject = {};
|
332 |
+
|
333 |
+
if ( queryString ) {
|
334 |
+
for ( var key in queryString ) {
|
335 |
+
queryObject = tvc_convertQueryStringToQueryObject( queryString[ key ] );
|
336 |
+
}
|
337 |
+
}
|
338 |
+
|
339 |
+
return queryObject;
|
340 |
+
}
|
341 |
+
|
342 |
+
function tvc_valueStringToValueObject( valueString ) {
|
343 |
+
var valueObject = {};
|
344 |
+
|
345 |
+
if ( valueString ) {
|
346 |
+
for ( var key in valueString ) {
|
347 |
+
// do not process the query part of the string
|
348 |
+
if ( key !== 'q' ) {
|
349 |
+
valueObject = tvc_convertValueStringToValueObject( valueString[ key ] );
|
350 |
+
}
|
351 |
+
}
|
352 |
+
}
|
353 |
+
|
354 |
+
return valueObject;
|
355 |
+
}
|
356 |
+
|
357 |
+
function tvc_convertQueryStringToQueryObject( queryString ) {
|
358 |
+
var queryObject = {};
|
359 |
+
|
360 |
+
var stringSplit = queryString.split( '#' );
|
361 |
+
|
362 |
+
if ( stringSplit[ 0 ] === '1' || stringSplit[ 0 ] === '2' ) {
|
363 |
+
queryObject.preCondition = stringSplit[ 0 ];
|
364 |
+
} else {
|
365 |
+
queryObject.preCondition = '0';
|
366 |
+
}
|
367 |
+
|
368 |
+
queryObject.source = stringSplit[ 1 ];
|
369 |
+
queryObject.condition = stringSplit[ 2 ];
|
370 |
+
queryObject.value = stringSplit[ 3 ] ? stringSplit[ 3 ] : '';
|
371 |
+
queryObject.endValue = stringSplit[ 5 ] ? stringSplit[ 5 ] : '';
|
372 |
+
|
373 |
+
return queryObject;
|
374 |
+
}
|
375 |
+
|
376 |
+
function tvc_resortObject( object ) {
|
377 |
+
var result = [];
|
378 |
+
var i = 1;
|
379 |
+
|
380 |
+
// re-sort the conditions
|
381 |
+
for ( var element in object ) {
|
382 |
+
var o = {};
|
383 |
+
for ( var key in object[ element ] ) {
|
384 |
+
if ( key !== 'q' ) { // exclude q as key
|
385 |
+
o[ i ] = object[ element ][ key ];
|
386 |
+
result.push( o );
|
387 |
+
} else {
|
388 |
+
result[ i - 1 ].q = object[ element ][ key ];
|
389 |
+
}
|
390 |
+
}
|
391 |
+
|
392 |
+
i ++;
|
393 |
+
}
|
394 |
+
|
395 |
+
// don't return an empty {} string
|
396 |
+
return i > 1 ? result : '';
|
397 |
+
}
|
398 |
+
|
399 |
+
function tvc_convertValueStringToValueObject( valueString ) {
|
400 |
+
var valueObject = {};
|
401 |
+
var valueSplit = valueString.split( '#' );
|
402 |
+
|
403 |
+
valueObject.preCondition = valueSplit[ 0 ];
|
404 |
+
valueObject.condition = valueSplit[ 1 ];
|
405 |
+
valueObject.value = valueSplit[ 2 ];
|
406 |
+
valueObject.endValue = valueSplit[ 3 ] ? valueSplit[ 3 ] : '';
|
407 |
+
|
408 |
+
return valueObject;
|
409 |
+
}
|
410 |
+
|
411 |
+
function tvc_makeCleanQueryObject() {
|
412 |
+
var queryObject = {};
|
413 |
+
|
414 |
+
queryObject.preCondition = 'if';
|
415 |
+
queryObject.source = 'select';
|
416 |
+
queryObject.condition = '';
|
417 |
+
queryObject.value = '';
|
418 |
+
queryObject.endValue = '';
|
419 |
+
|
420 |
+
return queryObject;
|
421 |
+
}
|
422 |
+
|
423 |
+
function tvc_makeCleanValueObject() {
|
424 |
+
var valueObject = {};
|
425 |
+
|
426 |
+
valueObject.preCondition = 'change';
|
427 |
+
valueObject.condition = 'overwrite';
|
428 |
+
valueObject.value = '';
|
429 |
+
valueObject.endValue = '';
|
430 |
+
|
431 |
+
return valueObject;
|
432 |
+
}
|
433 |
+
|
434 |
+
function tvc_addNewItemToCategoryString(
|
435 |
+
level, oldString, newValue, separator ) {
|
436 |
+
var categoryLevel = oldString.split( separator ).length;
|
437 |
+
|
438 |
+
if ( oldString === tvc_feed_settings_form_vars.map_to_default_category || level === '0' ) {
|
439 |
+
return newValue;
|
440 |
+
} else {
|
441 |
+
if ( categoryLevel <= level ) {
|
442 |
+
return oldString + separator + newValue;
|
443 |
+
} else {
|
444 |
+
var pos = 0;
|
445 |
+
|
446 |
+
for ( var i = 0; i < level; i ++ ) {
|
447 |
+
pos = oldString.indexOf( separator, pos + 1 );
|
448 |
+
var oldPart = oldString.substring( 0, pos );
|
449 |
+
}
|
450 |
+
|
451 |
+
return oldPart + separator + newValue;
|
452 |
+
}
|
453 |
+
}
|
454 |
+
}
|
includes/application/js/tvc_logic.min.js
ADDED
@@ -0,0 +1,343 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
var _feedHolder;
|
2 |
+
|
3 |
+
function tvc_editCategories() {
|
4 |
+
var d = jQuery("#category-selector-lvl");
|
5 |
+
if (!tvc_isCustomChannel(_feedHolder.channel)) {
|
6 |
+
var e = _feedHolder.mainCategory.split(" > ");
|
7 |
+
var c = e.length;
|
8 |
+
var a = jQuery("#lvl_" + (c)).html() !== "" ? c + 1 : c;
|
9 |
+
jQuery("#selected-categories").hide();
|
10 |
+
jQuery("#lvl_0").prop("disabled", false);
|
11 |
+
for (var b = 0; b < a; b++) {
|
12 |
+
var f = jQuery("#lvl_" + b);
|
13 |
+
if (!e[b]) {
|
14 |
+
f.val("0")
|
15 |
+
}
|
16 |
+
f.show()
|
17 |
+
}
|
18 |
+
} else {
|
19 |
+
d.html(tvc_freeCategoryInputCntrl("default", _feedHolder.feedId, _feedHolder.mainCategory));
|
20 |
+
d.prop("disabled", false)
|
21 |
+
}
|
22 |
+
}
|
23 |
+
|
24 |
+
function tvc_generateFeed() {
|
25 |
+
if (jQuery("#file-name").val() !== "") {
|
26 |
+
if (_feedHolder.categoryMapping && _feedHolder.categoryMapping.length > 0) {
|
27 |
+
disableFeedActionButtons();
|
28 |
+
tvc_generateAndSaveFeed();
|
29 |
+
} else {
|
30 |
+
var a = confirm(tvc_feed_settings_form_vars.no_category_selected);
|
31 |
+
if (a === true) {
|
32 |
+
disableFeedActionButtons();
|
33 |
+
tvc_generateAndSaveFeed();
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
} else {
|
38 |
+
jQuery("#alert-message").html("<p>" + tvc_feed_settings_form_vars.file_name_required + "</p>");
|
39 |
+
jQuery("#success-message").show()
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
function tvc_saveFeedData() {
|
44 |
+
if (jQuery("#file-name").val() !== "") {
|
45 |
+
tvc_saveFeed()
|
46 |
+
} else {
|
47 |
+
jQuery("#alert-message").html("<p>" + tvc_feed_settings_form_vars.file_name_required + "</p>");
|
48 |
+
jQuery("#success-message").show()
|
49 |
+
}
|
50 |
+
}
|
51 |
+
|
52 |
+
function getCombinedValue(g, f) {
|
53 |
+
var h = 1;
|
54 |
+
var b = "";
|
55 |
+
var d = _feedHolder.getCombinedOutputValue(g, f);
|
56 |
+
while (jQuery("#combined-input-field-cntrl-" + g + "-" + f + "-" + h).val()) {
|
57 |
+
var a = g + "-" + f + "-" + h;
|
58 |
+
var e = jQuery("#combined-input-field-cntrl-" + a).val();
|
59 |
+
b += h > 1 ? jQuery("#combined-separator-cntrl-" + a).val() + "#" : "";
|
60 |
+
if (e !== "static") {
|
61 |
+
b += e !== "select" ? e + "|" : ""
|
62 |
+
} else {
|
63 |
+
if (jQuery("#static-input-field-" + a).val()) {
|
64 |
+
b += e + "#" + jQuery("#static-input-field-" + a).val() + "|"
|
65 |
+
} else {
|
66 |
+
b = d + "|";
|
67 |
+
break
|
68 |
+
}
|
69 |
+
}
|
70 |
+
h++
|
71 |
+
}
|
72 |
+
b = b.substring(0, b.length - 1);
|
73 |
+
return h > 1 ? b : false
|
74 |
+
}
|
75 |
+
|
76 |
+
function tvc_staticValueChanged(c, b, a) {
|
77 |
+
if (a > 0) {
|
78 |
+
tvc_changedCombinedOutput(c, b, a)
|
79 |
+
} else {
|
80 |
+
tvc_setStaticValue(c, b, a);
|
81 |
+
if (c === 34) {
|
82 |
+
tvc_setIdentifierExistsDependancies()
|
83 |
+
}
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
function tvc_changedOutputSelection(b) {
|
88 |
+
var a = jQuery("#output-field-cntrl-" + b);
|
89 |
+
if (a.val() !== "no-value") {
|
90 |
+
tvc_activateOptionalFieldRow(b, a.val())
|
91 |
+
}
|
92 |
+
}
|
93 |
+
|
94 |
+
function tvc_hasExtraSourceRow(a, b) {
|
95 |
+
if (b.length > 0) {
|
96 |
+
return b[a - 1].hasOwnProperty("c")
|
97 |
+
} else {
|
98 |
+
return false
|
99 |
+
}
|
100 |
+
}
|
101 |
+
|
102 |
+
function tvc_changedCustomOutputTitle() {
|
103 |
+
var a = jQuery("#custom-output-title-input").val();
|
104 |
+
if (a) {
|
105 |
+
tvc_activateCustomFieldRow(a)
|
106 |
+
}
|
107 |
+
}
|
108 |
+
|
109 |
+
function tvc_deleteSpecificFeed(c, b) {
|
110 |
+
var a = confirm(tvc_feed_list_form_vars.confirm_delete_feed.replace("%feedname%", b));
|
111 |
+
if (a === true) {
|
112 |
+
tvc_deleteFeed(c, b);
|
113 |
+
console.log("File " + b + " removed from server.");
|
114 |
+
tvc_show_success_message(tvc_feed_list_form_vars.feed_removed.replace("%feedname%", b))
|
115 |
+
parent.location='admin.php?page=tvc-product-feed-manager&tab=feed-list';
|
116 |
+
}
|
117 |
+
}
|
118 |
+
|
119 |
+
function tvc_alertRemoveChannel() {
|
120 |
+
var a = confirm(tvc_manage_channels_vars.confirm_removing_channel);
|
121 |
+
if (true !== a) {
|
122 |
+
return false
|
123 |
+
}
|
124 |
+
}
|
125 |
+
|
126 |
+
function tvc_valueOptionChanged(d, c, e) {
|
127 |
+
var b = jQuery("#value-options-" + d + "-" + c + "-" + e).val();
|
128 |
+
var a = tvc_getCorrectValueSelector(d, c, 0, b, "", "");
|
129 |
+
jQuery("#value-editor-input-span-" + d + "-" + c + "-" + e).html(a)
|
130 |
+
}
|
131 |
+
|
132 |
+
function tvc_getCorrectValueSelector(f, e, g, c, d, a) {
|
133 |
+
var b = "";
|
134 |
+
switch (c) {
|
135 |
+
case"0":
|
136 |
+
case"change nothing":
|
137 |
+
tvc_valueInputOptionsChanged(f, e, g);
|
138 |
+
b = "";
|
139 |
+
break;
|
140 |
+
case"1":
|
141 |
+
case"overwrite":
|
142 |
+
b = tvc_valueOptionsSingleInput(f, e, g, d);
|
143 |
+
break;
|
144 |
+
case"2":
|
145 |
+
case"replace":
|
146 |
+
b = tvc_valueOptionsReplaceInput(f, e, g, d, a);
|
147 |
+
break;
|
148 |
+
case"3":
|
149 |
+
case"remove":
|
150 |
+
case"4":
|
151 |
+
case"add prefix":
|
152 |
+
case"5":
|
153 |
+
case"add suffix":
|
154 |
+
b = tvc_valueOptionsSingleInputValue(f, e, g, d);
|
155 |
+
break;
|
156 |
+
case"6":
|
157 |
+
case"recalculate":
|
158 |
+
b = tvc_valueOptionsRecalculate(f, e, g, d, a);
|
159 |
+
break;
|
160 |
+
case"7":
|
161 |
+
case"convert to child-element":
|
162 |
+
b = tvc_valueOptionsElementInput(f, e, g, d);
|
163 |
+
break;
|
164 |
+
default:
|
165 |
+
b = tvc_valueOptionsSingleInput(f, e, g, d);
|
166 |
+
break
|
167 |
+
}
|
168 |
+
return b
|
169 |
+
}
|
170 |
+
|
171 |
+
function tvc_deactivateFeed(a) {
|
172 |
+
tvc_switchFeedStatus(a, function (b) {
|
173 |
+
tvc_updateFeedRowStatus(a, parseInt(b))
|
174 |
+
})
|
175 |
+
}
|
176 |
+
|
177 |
+
function tvc_duplicateFeed(b, a) {
|
178 |
+
tvc_duplicateExistingFeed(b, function (c) {
|
179 |
+
if (c) {
|
180 |
+
tvc_show_success_message(tvc_feed_list_form_vars.added_feed_copy.replace("%feedname%", a))
|
181 |
+
}
|
182 |
+
})
|
183 |
+
}
|
184 |
+
|
185 |
+
function tvc_regenerateFeed(a) {
|
186 |
+
var b = tvcQueueStringIsEmpty() ? 3 : 4;
|
187 |
+
tvcAddToQueueString(a);
|
188 |
+
tvc_showFeedSpinner();
|
189 |
+
tvc_updateFeedRowStatus(a, b);
|
190 |
+
console.log("Started regenerating feed " + a);
|
191 |
+
tvc_updateFeedFile(a, function (d) {
|
192 |
+
tvc_hideFeedSpinner();
|
193 |
+
console.log(d);
|
194 |
+
var c = setInterval(function () {
|
195 |
+
tvc_getCurrentFeedStatus(a, function (f) {
|
196 |
+
var e = JSON.parse(f);
|
197 |
+
if ("3" !== e.status_id && "4" !== e.status_id) {
|
198 |
+
console.log(e);
|
199 |
+
tvc_resetFeedStatus(e);
|
200 |
+
tvc_resetFeedList();
|
201 |
+
clearInterval(c);
|
202 |
+
tvcRemoveFromQueueString(a)
|
203 |
+
}
|
204 |
+
})
|
205 |
+
}, 10000)
|
206 |
+
})
|
207 |
+
}
|
208 |
+
|
209 |
+
function tvc_viewFeed(a) {
|
210 |
+
if (-1 !== a.indexOf("http")) {
|
211 |
+
window.open(a)
|
212 |
+
} else {
|
213 |
+
alert(tvc_feed_list_form_vars.feed_not_generated)
|
214 |
+
}
|
215 |
+
}
|
216 |
+
|
217 |
+
function tvc_addRowValueEditor(c, b, d, a) {
|
218 |
+
jQuery("#end-row-id-" + c).remove();
|
219 |
+
jQuery("#row-" + c).append(tvc_valueEditor(c, b, d, a) + tvc_endrow(c));
|
220 |
+
jQuery("#value-editor-input-query-add-span-" + c + "-" + b + "-" + d).remove()
|
221 |
+
}
|
222 |
+
|
223 |
+
function tvc_convertToCamelCase(b) {
|
224 |
+
var a = b[0].toLowerCase();
|
225 |
+
for (var c = 1; c < b.length; c++) {
|
226 |
+
a += b[c].charAt(0).toUpperCase() + b[c].slice(1)
|
227 |
+
}
|
228 |
+
return a
|
229 |
+
}
|
230 |
+
|
231 |
+
function tvc_addValueEditorQuery(c, b, a) {
|
232 |
+
if (tvc_changeValueIsFilled(c, b, a)) {
|
233 |
+
if (tvc_queryIsFilled(c, (b - 1), 1)) {
|
234 |
+
tvc_showEditValueQuery(c, b, a, true)
|
235 |
+
} else {
|
236 |
+
alert(tvc_feed_settings_form_vars.query_requirements)
|
237 |
+
}
|
238 |
+
} else {
|
239 |
+
alert(tvc_feed_settings_form_vars.first_fill_in_change_value)
|
240 |
+
}
|
241 |
+
}
|
242 |
+
|
243 |
+
function tvc_queryStringToQueryObject(c) {
|
244 |
+
var b = {};
|
245 |
+
if (c) {
|
246 |
+
for (var a in c) {
|
247 |
+
b = tvc_convertQueryStringToQueryObject(c[a])
|
248 |
+
}
|
249 |
+
}
|
250 |
+
return b
|
251 |
+
}
|
252 |
+
|
253 |
+
function tvc_valueStringToValueObject(b) {
|
254 |
+
var a = {};
|
255 |
+
if (b) {
|
256 |
+
for (var c in b) {
|
257 |
+
if (c !== "q") {
|
258 |
+
a = tvc_convertValueStringToValueObject(b[c])
|
259 |
+
}
|
260 |
+
}
|
261 |
+
}
|
262 |
+
return a
|
263 |
+
}
|
264 |
+
|
265 |
+
function tvc_convertQueryStringToQueryObject(c) {
|
266 |
+
var b = {};
|
267 |
+
var a = c.split("#");
|
268 |
+
if (a[0] === "1" || a[0] === "2") {
|
269 |
+
b.preCondition = a[0]
|
270 |
+
} else {
|
271 |
+
b.preCondition = "0"
|
272 |
+
}
|
273 |
+
b.source = a[1];
|
274 |
+
b.condition = a[2];
|
275 |
+
b.value = a[3] ? a[3] : "";
|
276 |
+
b.endValue = a[5] ? a[5] : "";
|
277 |
+
return b
|
278 |
+
}
|
279 |
+
|
280 |
+
function tvc_resortObject(b) {
|
281 |
+
var a = [];
|
282 |
+
var e = 1;
|
283 |
+
for (var d in b) {
|
284 |
+
var f = {};
|
285 |
+
for (var c in b[d]) {
|
286 |
+
if (c !== "q") {
|
287 |
+
f[e] = b[d][c];
|
288 |
+
a.push(f)
|
289 |
+
} else {
|
290 |
+
a[e - 1].q = b[d][c]
|
291 |
+
}
|
292 |
+
}
|
293 |
+
e++
|
294 |
+
}
|
295 |
+
return e > 1 ? a : ""
|
296 |
+
}
|
297 |
+
|
298 |
+
function tvc_convertValueStringToValueObject(b) {
|
299 |
+
var a = {};
|
300 |
+
var c = b.split("#");
|
301 |
+
a.preCondition = c[0];
|
302 |
+
a.condition = c[1];
|
303 |
+
a.value = c[2];
|
304 |
+
a.endValue = c[3] ? c[3] : "";
|
305 |
+
return a
|
306 |
+
}
|
307 |
+
|
308 |
+
function tvc_makeCleanQueryObject() {
|
309 |
+
var a = {};
|
310 |
+
a.preCondition = "if";
|
311 |
+
a.source = "select";
|
312 |
+
a.condition = "";
|
313 |
+
a.value = "";
|
314 |
+
a.endValue = "";
|
315 |
+
return a
|
316 |
+
}
|
317 |
+
|
318 |
+
function tvc_makeCleanValueObject() {
|
319 |
+
var a = {};
|
320 |
+
a.preCondition = "change";
|
321 |
+
a.condition = "overwrite";
|
322 |
+
a.value = "";
|
323 |
+
a.endValue = "";
|
324 |
+
return a
|
325 |
+
}
|
326 |
+
|
327 |
+
function tvc_addNewItemToCategoryString(h, a, f, e) {
|
328 |
+
var b = a.split(e).length;
|
329 |
+
if (a === tvc_feed_settings_form_vars.map_to_default_category || h === "0") {
|
330 |
+
return f
|
331 |
+
} else {
|
332 |
+
if (b <= h) {
|
333 |
+
return a + e + f
|
334 |
+
} else {
|
335 |
+
var g = 0;
|
336 |
+
for (var c = 0; c < h; c++) {
|
337 |
+
g = a.indexOf(e, g + 1);
|
338 |
+
var d = a.substring(0, g)
|
339 |
+
}
|
340 |
+
return d + e + f
|
341 |
+
}
|
342 |
+
}
|
343 |
+
};
|
includes/application/js/tvc_object-attribute-meta.js
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"use strict";
|
2 |
+
|
3 |
+
function Tvc_AttributeMeta( key, value ) {
|
4 |
+
|
5 |
+
this.key = key;
|
6 |
+
this.value = value;
|
7 |
+
}
|
8 |
+
|
9 |
+
function countSources( mappingData ) {
|
10 |
+
|
11 |
+
return mappingData.length > 0 ? mappingData.length : 1;
|
12 |
+
}
|
13 |
+
|
14 |
+
function tvc_getMappingSourceValue( mapping, sourceCounter ) {
|
15 |
+
|
16 |
+
if ( mapping && mapping.length > 0 ) {
|
17 |
+
|
18 |
+
if ( mapping[ sourceCounter ] && 's' in mapping[ sourceCounter ] && 'source' in mapping[ sourceCounter ].s ) {
|
19 |
+
|
20 |
+
// do not return a combined value
|
21 |
+
return mapping[ sourceCounter ].s[ 'source' ] !== 'combined' ? mapping[ sourceCounter ].s[ 'source' ] : null;
|
22 |
+
} else {
|
23 |
+
return null;
|
24 |
+
}
|
25 |
+
} else {
|
26 |
+
return null; // mapping seems to be empty
|
27 |
+
}
|
28 |
+
}
|
29 |
+
|
30 |
+
function tvc_getMappingCombinedValue( mapping, sourceCounter ) {
|
31 |
+
|
32 |
+
if ( mapping && mapping.length > 0 ) {
|
33 |
+
|
34 |
+
if ( mapping[ sourceCounter ] && 's' in mapping[ sourceCounter ] && 'source' in mapping[ sourceCounter ].s && mapping[ sourceCounter ].s[ 'source' ] === 'combined' ) {
|
35 |
+
return mapping[ sourceCounter ].s[ 'f' ];
|
36 |
+
} else {
|
37 |
+
return null;
|
38 |
+
}
|
39 |
+
} else {
|
40 |
+
return null; // mapping seems to be empty
|
41 |
+
}
|
42 |
+
}
|
43 |
+
|
44 |
+
function tvc_getMappingStaticValue( mapping, sourceCounter ) {
|
45 |
+
|
46 |
+
if ( mapping && mapping.length > 0 ) {
|
47 |
+
|
48 |
+
if ( mapping[ sourceCounter ] && 's' in mapping[ sourceCounter ] && 'static' in mapping[ sourceCounter ].s ) {
|
49 |
+
return mapping[ sourceCounter ].s[ 'static' ];
|
50 |
+
} else {
|
51 |
+
return null;
|
52 |
+
}
|
53 |
+
} else {
|
54 |
+
return null; // mapping seems to be empty
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
function tvc_getMappingConditions( mapping, sourceCounter ) {
|
59 |
+
if ( mapping && mapping.length > 0 ) {
|
60 |
+
if ( mapping[ sourceCounter ] && 'c' in mapping[ sourceCounter ] ) {
|
61 |
+
return mapping[ sourceCounter ].c;
|
62 |
+
}
|
63 |
+
} else {
|
64 |
+
return null;
|
65 |
+
}
|
66 |
+
}
|
includes/application/js/tvc_object-attribute-meta.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
function Tvc_AttributeMeta(a,b){this.key=a;this.value=b}function countSources(a){return a.length>0?a.length:1}function tvc_getMappingSourceValue(b,a){if(b&&b.length>0){if(b[a]&&"s" in b[a]&&"source" in b[a].s){return b[a].s.source!=="combined"?b[a].s.source:null}else{return null}}else{return null}}function tvc_getMappingCombinedValue(b,a){if(b&&b.length>0){if(b[a]&&"s" in b[a]&&"source" in b[a].s&&b[a].s.source==="combined"){return b[a].s.f}else{return null}}else{return null}}function tvc_getMappingStaticValue(b,a){if(b&&b.length>0){if(b[a]&&"s" in b[a]&&"static" in b[a].s){return b[a].s["static"]}else{return null}}else{return null}}function tvc_getMappingConditions(b,a){if(b&&b.length>0){if(b[a]&&"c" in b[a]){return b[a].c}}else{return null}};
|
includes/application/js/tvc_object-feed.js
ADDED
@@ -0,0 +1,849 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"use strict";
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Feed Object
|
5 |
+
*
|
6 |
+
* @param {int} feedId
|
7 |
+
* @param {string} title Title of the feed file
|
8 |
+
* @param {int} includeVariations Does this feed include variations
|
9 |
+
* @param {int} aggregator Is this an aggregator feed
|
10 |
+
* @param {int} channel Channel definition
|
11 |
+
* @param {string} mainCategory
|
12 |
+
* @param {array} categoryMapping
|
13 |
+
* @param {string} url
|
14 |
+
* @param {string} dataSource Source id (for now only WooCommerce is supported)
|
15 |
+
* @param {string} country Two letter country identifier
|
16 |
+
* @param {string} language
|
17 |
+
* @param {string} feedTitle Google's feed title text
|
18 |
+
* @param {string} feedDescription Google's feed description text
|
19 |
+
* @param {string} updateSchedule Updates schedule string
|
20 |
+
* @param {array} feedFilter Feed filters
|
21 |
+
* @param {int} status Status of the feed
|
22 |
+
* @param {string} feedType Type of feed (default Product Feed Type)
|
23 |
+
*
|
24 |
+
* @constructor
|
25 |
+
*/
|
26 |
+
function Feed( feedId, title, includeVariations, aggregator, channel, mainCategory,
|
27 |
+
categoryMapping, url, dataSource, country, language, feedTitle,
|
28 |
+
feedDescription, updateSchedule, feedFilter, status, feedType ) {
|
29 |
+
|
30 |
+
this.feedId = feedId;
|
31 |
+
this.title = title;
|
32 |
+
this.mainCategory = mainCategory;
|
33 |
+
this.categoryMapping = categoryMapping;
|
34 |
+
this.includeVariations = includeVariations;
|
35 |
+
this.isAggregator = aggregator;
|
36 |
+
this.feedTitle = feedTitle;
|
37 |
+
this.feedDescription = feedDescription;
|
38 |
+
this.url = url;
|
39 |
+
this.dataSource = dataSource;
|
40 |
+
this.channel = channel;
|
41 |
+
this.country = channel !== '3' ? country : 'NL'; // for Beslist.nl only register the Netherlands
|
42 |
+
this.language = language;
|
43 |
+
this.status = status;
|
44 |
+
this.updateSchedule = updateSchedule;
|
45 |
+
this.feedFilter = feedFilter;
|
46 |
+
this.attributes = [];
|
47 |
+
this.feedType = feedType;
|
48 |
+
|
49 |
+
// objects functions
|
50 |
+
this.addAttribute = addAttributeToFeed;
|
51 |
+
this.getAttributeIdByName = getAttributeId;
|
52 |
+
this.activateAttribute = activateFeedsAttribute;
|
53 |
+
this.checkIfCustomNameExists = checkCustomName;
|
54 |
+
this.countCombinedFields = countAttributesCombinedFields;
|
55 |
+
this.deactivateAttribute = deactivateFeedsAttribute;
|
56 |
+
this.deactivateCategory = deactivateCategoryMap;
|
57 |
+
this.activateCategory = activateCategoryMap;
|
58 |
+
this.setStaticAttributeValue = setAttributesStaticValue;
|
59 |
+
this.setSourceValue = setAttributesSourceValue;
|
60 |
+
this.setAlternativeSourceValue = setAlternativeAttributesSourceValue;
|
61 |
+
this.setCombinedOutputValue = setAttributesCombinedOutputValue;
|
62 |
+
this.setCategoryValue = setAttributesCategoryValue;
|
63 |
+
this.setFeedFilter = setFeedFilterValue;
|
64 |
+
this.mapCategory = mapACategory;
|
65 |
+
this.changeCustomFeedCategoryMap = changeCustomCategoryMap;
|
66 |
+
this.changeIncludeVariations = changeIncludeVariationsValue;
|
67 |
+
this.changeAggregator = changeAggregatorValue;
|
68 |
+
this.resetNrQueries = rstNrQueries;
|
69 |
+
this.incrNrQueries = addNrQueries;
|
70 |
+
this.decrNrQueries = substrNrQueries;
|
71 |
+
this.addConditionValue = addAttributesCondition;
|
72 |
+
this.addValueQueryValue = addAttributesValueQuery;
|
73 |
+
this.removeAttribute = removeAttributeFromFeed;
|
74 |
+
this.removeValueConditionValue = removeAttributesCondition;
|
75 |
+
this.removeValueQueryValue = removeAttributesValueQuery;
|
76 |
+
this.removeAlternativeSourceValue = removeAlternativeSource;
|
77 |
+
this.removeCombinedOutputValue = removeAttributesCombinedOutputValue;
|
78 |
+
this.removeEditValueValue = removeAttributesEditValue;
|
79 |
+
this.removeFeedFilter = removeFeedFilterValue;
|
80 |
+
this.getAttributesQueriesObject = getAttributesQueries;
|
81 |
+
this.getCombinedOutputValue = getAttributesCombinedOutputValue;
|
82 |
+
this.getValueQueryValue = getAttributesValueQueries;
|
83 |
+
this.getAttributesSourceObject = getAttributesSources;
|
84 |
+
this.getSourceObject = getSourceData;
|
85 |
+
this.getAlternativeSourcesObject = getAlternativeSources;
|
86 |
+
this.getAttributesValueObject = getAttributesValues;
|
87 |
+
this.getFeedFilter = getFeedFilterValue;
|
88 |
+
this.getFeedType = getFeedType;
|
89 |
+
this.setMainCategory = setCategories;
|
90 |
+
this.setUpdateSchedule = setSchedule;
|
91 |
+
this.setCustomCategory = setFeedCustomCategory;
|
92 |
+
this.setCountry = changeCountry;
|
93 |
+
this.clearSourceValue = clearAttributesSourceValue;
|
94 |
+
this.cleanAttributes = cleanUnusedAttributes;
|
95 |
+
this.clearAllAttributes = clearAttributes;
|
96 |
+
this.addChangeValue = addAttributesChangeValue;
|
97 |
+
}
|
98 |
+
|
99 |
+
function FeedAttribute( attributeId, fieldName, advisedSource, value, fieldLevel, isActive,
|
100 |
+
nrQueries, nrValueEdits, nrValueConditions ) {
|
101 |
+
|
102 |
+
this.rowId = attributeId;
|
103 |
+
this.fieldName = fieldName;
|
104 |
+
this.advisedSource = advisedSource;
|
105 |
+
this.value = value;
|
106 |
+
this.fieldLevel = fieldLevel;
|
107 |
+
this.isActive = isActive;
|
108 |
+
this.nrQueries = nrQueries;
|
109 |
+
this.nrValueEdits = nrValueEdits;
|
110 |
+
this.nrValueConditions = nrValueConditions;
|
111 |
+
}
|
112 |
+
|
113 |
+
function CategoryMap( shopCategory, feedCategories ) {
|
114 |
+
|
115 |
+
this.shopCategoryId = shopCategory;
|
116 |
+
this.feedCategories = feedCategories;
|
117 |
+
}
|
118 |
+
|
119 |
+
function addAttributeToFeed( attributeId, fieldName, advisedSource, value, fieldLevel, isActive, queryLevel, valuesLevel, valueConditions ) {
|
120 |
+
|
121 |
+
var attribute = new FeedAttribute( attributeId, fieldName, advisedSource, value, fieldLevel, isActive, queryLevel, valuesLevel, valueConditions );
|
122 |
+
|
123 |
+
this.attributes.push( attribute );
|
124 |
+
}
|
125 |
+
|
126 |
+
function removeAttributeFromFeed( rowId ) {
|
127 |
+
|
128 |
+
for ( var i = 0; i < this.attributes.length; i ++ ) {
|
129 |
+
|
130 |
+
if ( this.attributes[ i ].rowId === rowId ) {
|
131 |
+
|
132 |
+
this.attributes.splice( i, 1 );
|
133 |
+
}
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
function mapACategory( categorySelectorId, category ) {
|
138 |
+
|
139 |
+
var selectedLevel = categorySelectorId.match( /(\d+)$/ )[ 0 ]; // next level
|
140 |
+
var sc = categorySelectorId.replace( '_' + selectedLevel, '' );
|
141 |
+
var shopCategoryId = sc.match( /(\d+)$/ )[ 0 ];
|
142 |
+
var mo = JSON.parse( this.categoryMapping );
|
143 |
+
|
144 |
+
// check if this.categoryMapping already has a mapped category with this id
|
145 |
+
var categoryMapForGivenId = jQuery.grep(
|
146 |
+
mo,
|
147 |
+
function( e ) {
|
148 |
+
return e.shopCategoryId === shopCategoryId;
|
149 |
+
}
|
150 |
+
);
|
151 |
+
|
152 |
+
if ( categoryMapForGivenId.length > 0 ) {
|
153 |
+
|
154 |
+
var oldString = categoryMapForGivenId[ 0 ].feedCategories;
|
155 |
+
|
156 |
+
categoryMapForGivenId[ 0 ].feedCategories = tvc_addNewItemToCategoryString(
|
157 |
+
selectedLevel,
|
158 |
+
oldString,
|
159 |
+
category,
|
160 |
+
' > '
|
161 |
+
);
|
162 |
+
} else { // this category map does not exist so add a new one to the array
|
163 |
+
|
164 |
+
var catMap = new CategoryMap();
|
165 |
+
|
166 |
+
catMap.shopCategoryId = shopCategoryId;
|
167 |
+
catMap.feedCategories = category;
|
168 |
+
|
169 |
+
mo.push( catMap );
|
170 |
+
}
|
171 |
+
|
172 |
+
this.categoryMapping = JSON.stringify( mo );
|
173 |
+
}
|
174 |
+
|
175 |
+
function changeCustomCategoryMap( shopCategoryId, feedCategories ) {
|
176 |
+
|
177 |
+
var mo = JSON.parse( this.categoryMapping );
|
178 |
+
|
179 |
+
// check if this.categoryMapping already has a maped category with this id
|
180 |
+
var categoryMapForGivenId = jQuery.grep(
|
181 |
+
mo,
|
182 |
+
function( e ) {
|
183 |
+
return e.shopCategoryId === shopCategoryId;
|
184 |
+
}
|
185 |
+
);
|
186 |
+
|
187 |
+
if ( categoryMapForGivenId.length > 0 ) {
|
188 |
+
|
189 |
+
categoryMapForGivenId[ 0 ].feedCategories = feedCategories;
|
190 |
+
} else { // this category map does not exist so add a new one to the array
|
191 |
+
|
192 |
+
var catMap = new CategoryMap();
|
193 |
+
|
194 |
+
catMap.shopCategoryId = shopCategoryId;
|
195 |
+
catMap.feedCategories = feedCategories;
|
196 |
+
|
197 |
+
mo.push( catMap );
|
198 |
+
}
|
199 |
+
|
200 |
+
this.categoryMapping = JSON.stringify( mo );
|
201 |
+
}
|
202 |
+
|
203 |
+
function changeIncludeVariationsValue( selectedValue ) {
|
204 |
+
|
205 |
+
this.includeVariations = selectedValue ? '1' : '0';
|
206 |
+
}
|
207 |
+
|
208 |
+
function changeAggregatorValue( selectedValue ) {
|
209 |
+
|
210 |
+
this.isAggregator = selectedValue ? '1' : '0';
|
211 |
+
}
|
212 |
+
|
213 |
+
function activateCategoryMap( shopCategoryId, channelUsesOwnCategory ) {
|
214 |
+
|
215 |
+
// get the currently stored mapping
|
216 |
+
var mo = this.categoryMapping.length > 0 ? JSON.parse( this.categoryMapping ) : [];
|
217 |
+
|
218 |
+
// test if this.categoryMapping already has a mapped category with this id
|
219 |
+
var categoryMapForGivenId = jQuery.grep(
|
220 |
+
mo,
|
221 |
+
function( e ) {
|
222 |
+
return e.shopCategoryId === shopCategoryId.toString();
|
223 |
+
}
|
224 |
+
);
|
225 |
+
|
226 |
+
// only store this mapping if it has not been registered already to this id
|
227 |
+
if ( categoryMapForGivenId.length < 1 ) {
|
228 |
+
|
229 |
+
var catMap = new CategoryMap();
|
230 |
+
|
231 |
+
catMap.shopCategoryId = shopCategoryId.toString();
|
232 |
+
catMap.feedCategories = channelUsesOwnCategory ? 'wp_ownCategory' : 'wp_mainCategory';
|
233 |
+
|
234 |
+
mo.push( catMap );
|
235 |
+
|
236 |
+
this.categoryMapping = JSON.stringify( mo );
|
237 |
+
}
|
238 |
+
}
|
239 |
+
|
240 |
+
function deactivateCategoryMap( shopCategoryId ) {
|
241 |
+
|
242 |
+
var mo = this.categoryMapping.length > 0 ? JSON.parse( this.categoryMapping ) : [];
|
243 |
+
|
244 |
+
if ( mo.length > 1 ) {
|
245 |
+
|
246 |
+
var index = tvc_arrayObjectIndexOf(
|
247 |
+
mo,
|
248 |
+
shopCategoryId.toString(),
|
249 |
+
'shopCategoryId'
|
250 |
+
);
|
251 |
+
|
252 |
+
mo.splice( index, 1 ); // remove the category object
|
253 |
+
|
254 |
+
this.categoryMapping = JSON.stringify( mo );
|
255 |
+
} else {
|
256 |
+
|
257 |
+
this.categoryMapping = [];
|
258 |
+
}
|
259 |
+
}
|
260 |
+
|
261 |
+
function getAttributeId( name ) {
|
262 |
+
|
263 |
+
var attributeId = false;
|
264 |
+
|
265 |
+
for ( var i = 0; i < this.attributes.length; i ++ ) {
|
266 |
+
|
267 |
+
if ( this.attributes[ i ][ 'fieldName' ] === name ) {
|
268 |
+
|
269 |
+
attributeId = this.attributes[ i ][ 'rowId' ];
|
270 |
+
break;
|
271 |
+
}
|
272 |
+
}
|
273 |
+
|
274 |
+
if ( attributeId === false ) { // seems like a custom field
|
275 |
+
|
276 |
+
attributeId = this.attributes.length;
|
277 |
+
}
|
278 |
+
|
279 |
+
return attributeId;
|
280 |
+
}
|
281 |
+
|
282 |
+
function setAttributesStaticValue(
|
283 |
+
attributeId, level, combinationLevel, newValue ) {
|
284 |
+
var currentValue = this.attributes[ attributeId ][ 'value' ];
|
285 |
+
|
286 |
+
this.attributes[ attributeId ][ 'value' ] = tvc_storeSourceValue( level, currentValue, 'static', newValue );
|
287 |
+
|
288 |
+
this.attributes[ attributeId ][ 'isActive' ] = ! ! this.attributes[ attributeId ][ 'value' ];
|
289 |
+
}
|
290 |
+
|
291 |
+
function setAttributesSourceValue( attributeId, sourceLevel, newSource ) {
|
292 |
+
var currentValue = this.attributes[ attributeId ][ 'value' ];
|
293 |
+
this.attributes[ attributeId ][ 'value' ] = tvc_storeSourceValue(
|
294 |
+
sourceLevel,
|
295 |
+
currentValue,
|
296 |
+
'source',
|
297 |
+
newSource
|
298 |
+
);
|
299 |
+
}
|
300 |
+
|
301 |
+
function setAlternativeAttributesSourceValue( attributeId, level, value ) {
|
302 |
+
|
303 |
+
var attributeValueObject = {};
|
304 |
+
var attributeArray = [];
|
305 |
+
|
306 |
+
if ( this.attributes[ attributeId ][ 'value' ] ) {
|
307 |
+
attributeValueObject = JSON.parse(
|
308 |
+
this.attributes[ attributeId ][ 'value' ]
|
309 |
+
);
|
310 |
+
|
311 |
+
attributeValueObject.a = addOrRemoveValueInValueString(
|
312 |
+
attributeValueObject.a,
|
313 |
+
value,
|
314 |
+
level,
|
315 |
+
'add'
|
316 |
+
);
|
317 |
+
} else {
|
318 |
+
|
319 |
+
var o = {};
|
320 |
+
o[ 1 ] = value;
|
321 |
+
|
322 |
+
attributeArray.push( o );
|
323 |
+
attributeValueObject.a = attributeArray;
|
324 |
+
}
|
325 |
+
|
326 |
+
this.attributes[ attributeId ][ 'value' ] = JSON.stringify( attributeValueObject );
|
327 |
+
}
|
328 |
+
|
329 |
+
function setAttributesCombinedOutputValue(
|
330 |
+
attributeId, sourceLevel, newCombinedValue ) {
|
331 |
+
|
332 |
+
var currentValue = this.attributes[ attributeId ][ 'value' ];
|
333 |
+
console.log( currentValue );
|
334 |
+
|
335 |
+
this.attributes[ attributeId ][ 'value' ] = tvc_storeCombinedValue(
|
336 |
+
sourceLevel,
|
337 |
+
currentValue,
|
338 |
+
newCombinedValue
|
339 |
+
);
|
340 |
+
}
|
341 |
+
|
342 |
+
function getAttributesCombinedOutputValue( attributeId, sourceLevel ) {
|
343 |
+
|
344 |
+
var attributeObject = this.attributes[ attributeId ][ 'value' ] ? JSON.parse( this.attributes[ attributeId ][ 'value' ] ) : {};
|
345 |
+
|
346 |
+
if ( attributeObject && attributeObject.m && attributeObject.m[ sourceLevel ] && attributeObject.m[ sourceLevel ].s && attributeObject.m[ sourceLevel ].s.f ) {
|
347 |
+
|
348 |
+
return attributeObject.m[ sourceLevel ].s.f;
|
349 |
+
} else {
|
350 |
+
|
351 |
+
return '';
|
352 |
+
}
|
353 |
+
}
|
354 |
+
|
355 |
+
function removeAttributesCombinedOutputValue(
|
356 |
+
attributeId, sourceLevel, combinedLevel ) {
|
357 |
+
|
358 |
+
var currentValue = this.attributes[ attributeId ][ 'value' ];
|
359 |
+
this.attributes[ attributeId ][ 'value' ] = tvc_removeCombinedValue(
|
360 |
+
sourceLevel,
|
361 |
+
combinedLevel,
|
362 |
+
currentValue
|
363 |
+
);
|
364 |
+
}
|
365 |
+
|
366 |
+
function countAttributesCombinedFields( attributeId ) {
|
367 |
+
|
368 |
+
if ( this.attributes[ attributeId ][ 'value' ] ) {
|
369 |
+
var attributeValueObject = JSON.parse(
|
370 |
+
this.attributes[ attributeId ][ 'value' ]
|
371 |
+
);
|
372 |
+
|
373 |
+
if ( attributeValueObject.hasOwnProperty( 'f' ) ) {
|
374 |
+
return tvc_countObjectItems( attributeValueObject.f );
|
375 |
+
} else {
|
376 |
+
return 0;
|
377 |
+
}
|
378 |
+
} else {
|
379 |
+
return 0;
|
380 |
+
}
|
381 |
+
}
|
382 |
+
|
383 |
+
function setAttributesCategoryValue( attributeId, newCategory ) {
|
384 |
+
|
385 |
+
var currentValue = this.attributes[ attributeId ][ 'value' ];
|
386 |
+
this.attributes[ attributeId ][ 'value' ] = tvc_storeSourceValue(
|
387 |
+
0,
|
388 |
+
currentValue,
|
389 |
+
'',
|
390 |
+
newCategory
|
391 |
+
);
|
392 |
+
}
|
393 |
+
|
394 |
+
function rstNrQueries( attributeId ) {
|
395 |
+
this.attributes[ attributeId ][ 'nrQueries' ] = 0;
|
396 |
+
}
|
397 |
+
|
398 |
+
function addNrQueries( attributeId ) {
|
399 |
+
var currentNr = this.attributes[ attributeId ][ 'nrQueries' ];
|
400 |
+
this.attributes[ attributeId ][ 'nrQueries' ] = currentNr + 1;
|
401 |
+
}
|
402 |
+
|
403 |
+
function substrNrQueries( attributeId ) {
|
404 |
+
|
405 |
+
var currentNr = this.attributes[ attributeId ][ 'nrQueries' ];
|
406 |
+
if ( currentNr > 0 ) {
|
407 |
+
this.attributes[ attributeId ][ 'nrQueries' ] = currentNr - 1;
|
408 |
+
}
|
409 |
+
}
|
410 |
+
|
411 |
+
function addAttributesChangeValue(
|
412 |
+
attributeId, sourceLevel, valueEditorLevel, value ) {
|
413 |
+
var currentValue = this.attributes[ attributeId ][ 'value' ];
|
414 |
+
this.attributes[ attributeId ][ 'value' ] = tvc_storeValueChange(
|
415 |
+
sourceLevel,
|
416 |
+
valueEditorLevel,
|
417 |
+
value,
|
418 |
+
'add',
|
419 |
+
currentValue
|
420 |
+
);
|
421 |
+
}
|
422 |
+
|
423 |
+
function addAttributesCondition(
|
424 |
+
attributeId, newCondition, sourceLevel, conditionLevel ) {
|
425 |
+
var currentValue = this.attributes[ attributeId ][ 'value' ];
|
426 |
+
this.attributes[ attributeId ][ 'value' ] = tvc_storeConditionValue(
|
427 |
+
sourceLevel,
|
428 |
+
conditionLevel,
|
429 |
+
currentValue,
|
430 |
+
newCondition
|
431 |
+
);
|
432 |
+
}
|
433 |
+
|
434 |
+
function addAttributesValueQuery(
|
435 |
+
attributeId, sourceLevel, queryLevel, queryToAdd ) {
|
436 |
+
var currentValue = this.attributes[ attributeId ][ 'value' ];
|
437 |
+
this.attributes[ attributeId ][ 'value' ] = tvc_storeQueryValue(
|
438 |
+
sourceLevel,
|
439 |
+
queryLevel,
|
440 |
+
currentValue,
|
441 |
+
queryToAdd
|
442 |
+
);
|
443 |
+
}
|
444 |
+
|
445 |
+
function setFeedFilterValue( value ) {
|
446 |
+
this.feedFilter = value;
|
447 |
+
}
|
448 |
+
|
449 |
+
function removeFeedFilterValue( filterLevelToRemove ) {
|
450 |
+
this.feedFilter = removeFeedFilterLevel(
|
451 |
+
this.feedFilter,
|
452 |
+
filterLevelToRemove
|
453 |
+
);
|
454 |
+
}
|
455 |
+
|
456 |
+
function removeAttributesCondition( attributeId, sourceLevel, conditionLevel ) {
|
457 |
+
var currentValue = this.attributes[ attributeId ][ 'value' ];
|
458 |
+
this.attributes[ attributeId ][ 'value' ] = tvc_removeConditionValue(
|
459 |
+
sourceLevel,
|
460 |
+
conditionLevel,
|
461 |
+
currentValue
|
462 |
+
);
|
463 |
+
}
|
464 |
+
|
465 |
+
function removeAttributesValueQuery( attributeId, sourceLevel, queryLevel ) {
|
466 |
+
var currentValue = this.attributes[ attributeId ][ 'value' ];
|
467 |
+
this.attributes[ attributeId ][ 'value' ] = tvc_removeQueryValue(
|
468 |
+
sourceLevel,
|
469 |
+
queryLevel,
|
470 |
+
currentValue
|
471 |
+
);
|
472 |
+
}
|
473 |
+
|
474 |
+
function removeAttributesEditValue(
|
475 |
+
attributeId, sourceLevel, valueEditorLevel ) {
|
476 |
+
var currentValue = this.attributes[ attributeId ][ 'value' ];
|
477 |
+
this.attributes[ attributeId ][ 'value' ] = tvc_removeEditValuesValue(
|
478 |
+
sourceLevel,
|
479 |
+
valueEditorLevel,
|
480 |
+
currentValue
|
481 |
+
);
|
482 |
+
}
|
483 |
+
|
484 |
+
function removeAlternativeSource( attributeId, level ) {
|
485 |
+
var attributeValueObject = {};
|
486 |
+
if ( this.attributes[ attributeId ][ 'value' ] ) {
|
487 |
+
attributeValueObject = JSON.parse(
|
488 |
+
this.attributes[ attributeId ][ 'value' ]
|
489 |
+
);
|
490 |
+
|
491 |
+
attributeValueObject.a = addOrRemoveValueInValueString(
|
492 |
+
attributeValueObject.a,
|
493 |
+
'',
|
494 |
+
level,
|
495 |
+
'remove'
|
496 |
+
);
|
497 |
+
|
498 |
+
if ( ! attributeValueObject.a ) {
|
499 |
+
delete attributeValueObject.a;
|
500 |
+
}
|
501 |
+
|
502 |
+
this.attributes[ attributeId ][ 'value' ] = JSON.stringify(
|
503 |
+
attributeValueObject
|
504 |
+
);
|
505 |
+
}
|
506 |
+
}
|
507 |
+
|
508 |
+
/**
|
509 |
+
* Gets the queries from a specific attribute
|
510 |
+
*
|
511 |
+
* @param {int} attributeId
|
512 |
+
* @param {int} sourceLevel
|
513 |
+
* @returns {array} containing the queries
|
514 |
+
*/
|
515 |
+
function getAttributesQueries( attributeId, sourceLevel ) {
|
516 |
+
|
517 |
+
var attributeString = this.attributes[ attributeId ][ 'value' ];
|
518 |
+
var queries = {};
|
519 |
+
if ( attributeString ) {
|
520 |
+
var o = JSON.parse( attributeString );
|
521 |
+
if ( o && o.hasOwnProperty( 'm' ) && o.m[ sourceLevel ] && o.m[ sourceLevel ].hasOwnProperty( 'c' ) && o.m[ sourceLevel ].c.length > 0 ) {
|
522 |
+
queries = o.m[ sourceLevel ].c;
|
523 |
+
}
|
524 |
+
}
|
525 |
+
|
526 |
+
return queries;
|
527 |
+
}
|
528 |
+
|
529 |
+
function getAttributesValueQueries( attributeId, sourceLevel ) {
|
530 |
+
|
531 |
+
var attributeString = this.attributes[ attributeId ][ 'value' ];
|
532 |
+
var queries = {};
|
533 |
+
|
534 |
+
if ( attributeString ) {
|
535 |
+
var attributeObject = JSON.parse( attributeString );
|
536 |
+
if ( attributeObject && attributeObject.v && attributeObject.v[ sourceLevel ] && attributeObject.v[ sourceLevel ].hasOwnProperty( 'q' ) && attributeObject.v[ sourceLevel ].q.length > 0 ) {
|
537 |
+
queries = attributeObject.v[ sourceLevel ].q;
|
538 |
+
}
|
539 |
+
}
|
540 |
+
return queries;
|
541 |
+
}
|
542 |
+
|
543 |
+
function getAttributesValues( attributeId ) {
|
544 |
+
|
545 |
+
var attributeString = this.attributes[ attributeId ][ 'value' ];
|
546 |
+
var values = {};
|
547 |
+
if ( attributeString ) {
|
548 |
+
var attributeObject = JSON.parse( attributeString );
|
549 |
+
if ( attributeObject && 'v' in attributeObject && attributeObject.v.length > 0 ) {
|
550 |
+
values = attributeObject.v;
|
551 |
+
}
|
552 |
+
}
|
553 |
+
return values;
|
554 |
+
}
|
555 |
+
|
556 |
+
function getFeedFilterValue( feedId ) {
|
557 |
+
|
558 |
+
}
|
559 |
+
|
560 |
+
function getAlternativeSources( attributeId ) {
|
561 |
+
|
562 |
+
var attributeString = this.attributes[ attributeId ][ 'value' ];
|
563 |
+
var values = {};
|
564 |
+
|
565 |
+
if ( attributeString ) {
|
566 |
+
|
567 |
+
var attributeObject = JSON.parse( attributeString );
|
568 |
+
|
569 |
+
if ( attributeObject && 'a' in attributeObject && attributeObject.a.length > 0 ) {
|
570 |
+
|
571 |
+
values = attributeObject.a;
|
572 |
+
}
|
573 |
+
}
|
574 |
+
|
575 |
+
return values;
|
576 |
+
}
|
577 |
+
|
578 |
+
/**
|
579 |
+
* Returns an object filled with all the required data for a specific feed row
|
580 |
+
*
|
581 |
+
* @param {string} feedId
|
582 |
+
* @returns {object} containing the required data
|
583 |
+
*/
|
584 |
+
function getSourceData( feedId ) {
|
585 |
+
|
586 |
+
var data = {};
|
587 |
+
|
588 |
+
// add the basic data to the object
|
589 |
+
data.rowId = feedId;
|
590 |
+
data.fieldName = this.attributes[ feedId ][ 'fieldName' ];
|
591 |
+
data.advisedSource = this.attributes[ feedId ][ 'advisedSource' ];
|
592 |
+
|
593 |
+
// get the attribute data
|
594 |
+
var attributeString = this.attributes[ feedId ][ 'value' ];
|
595 |
+
|
596 |
+
// and put the attribute data in the object
|
597 |
+
if ( attributeString ) {
|
598 |
+
|
599 |
+
var attributeDataObject = JSON.parse( attributeString );
|
600 |
+
|
601 |
+
data.mapping = attributeDataObject && 'm' in attributeDataObject ? attributeDataObject.m : [];
|
602 |
+
data.changeValues = attributeDataObject && 'v' in attributeDataObject ? attributeDataObject.v : [];
|
603 |
+
data.customCondition = ! ! (
|
604 |
+
attributeDataObject && 't' in attributeDataObject
|
605 |
+
);
|
606 |
+
} else {
|
607 |
+
|
608 |
+
data.mapping = [];
|
609 |
+
data.changeValues = [];
|
610 |
+
data.customCondition = false;
|
611 |
+
}
|
612 |
+
|
613 |
+
return data;
|
614 |
+
}
|
615 |
+
|
616 |
+
function getAttributesSources( attributeId ) {
|
617 |
+
|
618 |
+
var attributeString = this.attributes[ attributeId ][ 'value' ];
|
619 |
+
var source = {};
|
620 |
+
|
621 |
+
if ( attributeString ) {
|
622 |
+
|
623 |
+
var attributeObject = JSON.parse( attributeString );
|
624 |
+
|
625 |
+
if ( attributeObject && 's' in attributeObject ) {
|
626 |
+
|
627 |
+
source = attributeObject.s;
|
628 |
+
}
|
629 |
+
}
|
630 |
+
|
631 |
+
return source;
|
632 |
+
}
|
633 |
+
|
634 |
+
function addOrRemoveValueInValueString( values, value, level, add ) {
|
635 |
+
|
636 |
+
var valueArray = values ? values : [];
|
637 |
+
|
638 |
+
if ( add === 'add' ) {
|
639 |
+
|
640 |
+
var o = {};
|
641 |
+
var queriesMemory = '';
|
642 |
+
o[ level ] = value;
|
643 |
+
|
644 |
+
// if the value also has a query than store it first
|
645 |
+
if ( valueArray[ level - 1 ] && 'q' in valueArray[ level - 1 ] ) {
|
646 |
+
|
647 |
+
queriesMemory = valueArray[ level - 1 ][ 'q' ];
|
648 |
+
}
|
649 |
+
|
650 |
+
// remove values with the same key
|
651 |
+
if ( level in o ) {
|
652 |
+
|
653 |
+
valueArray.splice( level - 1, 1 );
|
654 |
+
}
|
655 |
+
|
656 |
+
// if there were queries stored, then put them back in to the new value
|
657 |
+
if ( queriesMemory ) {
|
658 |
+
o[ 'q' ] = queriesMemory;
|
659 |
+
}
|
660 |
+
|
661 |
+
valueArray.push( o );
|
662 |
+
} else { // remove
|
663 |
+
|
664 |
+
valueArray.splice( level - 1, 1 );
|
665 |
+
|
666 |
+
// re-sort the queries
|
667 |
+
valueArray = tvc_resortObject( valueArray );
|
668 |
+
}
|
669 |
+
|
670 |
+
if ( tvc_countObjectItems( valueArray ) > 0 ) {
|
671 |
+
|
672 |
+
return valueArray;
|
673 |
+
} else {
|
674 |
+
|
675 |
+
return '';
|
676 |
+
}
|
677 |
+
}
|
678 |
+
|
679 |
+
function clearAttributesSourceValue( attributeId, sourceLevel ) {
|
680 |
+
|
681 |
+
if ( this.attributes[ attributeId ][ 'value' ] ) {
|
682 |
+
|
683 |
+
this.attributes[ attributeId ][ 'value' ] = tvc_storeSourceValue(
|
684 |
+
sourceLevel,
|
685 |
+
this.attributes[ attributeId ][ 'value' ],
|
686 |
+
'clear',
|
687 |
+
''
|
688 |
+
);
|
689 |
+
} else {
|
690 |
+
|
691 |
+
this.attributes[ attributeId ][ 'value' ] = '';
|
692 |
+
}
|
693 |
+
}
|
694 |
+
|
695 |
+
function setFeedCustomCategory( rowId, category ) {
|
696 |
+
|
697 |
+
console.log( this.attributes );
|
698 |
+
console.log( category );
|
699 |
+
|
700 |
+
// set the main category
|
701 |
+
this.mainCategory = category;
|
702 |
+
|
703 |
+
var id = rowId ? rowId : getCustomCategoryAttributeId( this.attributes, category );
|
704 |
+
|
705 |
+
// when a output is initialised as category, then set the category in the correct row
|
706 |
+
if ( id ) {
|
707 |
+
|
708 |
+
console.log( id );
|
709 |
+
|
710 |
+
var o = this.attributes[ id ][ 'value' ] ? JSON.parse( this.attributes[ id ][ 'value' ] ) : {};
|
711 |
+
|
712 |
+
o.t = category;
|
713 |
+
|
714 |
+
this.attributes[ id ][ 'value' ] = JSON.stringify( o );
|
715 |
+
}
|
716 |
+
}
|
717 |
+
|
718 |
+
function changeCountry( selectedCountry ) {
|
719 |
+
|
720 |
+
this.country = selectedCountry;
|
721 |
+
}
|
722 |
+
|
723 |
+
function getCustomCategoryAttributeId( attr ) {
|
724 |
+
|
725 |
+
for ( var i = 0; i < attr.length; i ++ ) {
|
726 |
+
|
727 |
+
console.log( attr[ i ] );
|
728 |
+
|
729 |
+
var catObject = attr[ i ][ 'value' ] ? JSON.parse( attr[ i ][ 'value' ] ) : {};
|
730 |
+
|
731 |
+
console.log( catObject );
|
732 |
+
|
733 |
+
if ( catObject.hasOwnProperty( 't' ) ) {
|
734 |
+
|
735 |
+
return i;
|
736 |
+
}
|
737 |
+
}
|
738 |
+
}
|
739 |
+
|
740 |
+
function setCategories( level, category, channel ) {
|
741 |
+
if ( this.attributes[ 3 ] !== undefined ) {
|
742 |
+
var categoryAttributeObject = this.attributes[ 3 ][ 'value' ] ? JSON.parse( this.attributes[ 3 ][ 'value' ] ) : {};
|
743 |
+
var categoryDelimiter = tvc_category_separator( channel );
|
744 |
+
|
745 |
+
var categoryString = this.mainCategory;
|
746 |
+
var categoryLevel = this.attributes[ 3 ][ 'value' ] !== undefined ? categoryString.split( categoryDelimiter ).length : 0;
|
747 |
+
|
748 |
+
var selectedLevel = level.match( /(\d+)$/ )[ 0 ];
|
749 |
+
|
750 |
+
if ( selectedLevel === '0' ) {
|
751 |
+
this.mainCategory = category;
|
752 |
+
this.attributes[ 3 ][ 'value' ] = '{"t":"' + category + '"}';
|
753 |
+
} else {
|
754 |
+
if ( categoryLevel <= selectedLevel ) {
|
755 |
+
this.mainCategory += categoryDelimiter + category;
|
756 |
+
this.attributes[ 3 ][ 'value' ] = '{"t":"' + categoryAttributeObject.t + categoryDelimiter + category + '"}';
|
757 |
+
} else {
|
758 |
+
var pos = 0;
|
759 |
+
|
760 |
+
for ( var i = 0; i < selectedLevel; i ++ ) {
|
761 |
+
pos = categoryString.indexOf( categoryDelimiter, pos + 1 );
|
762 |
+
}
|
763 |
+
|
764 |
+
categoryString = categoryString.substring( 0, pos );
|
765 |
+
|
766 |
+
if ( category !== '0' ) {
|
767 |
+
this.mainCategory = categoryString + categoryDelimiter + category;
|
768 |
+
this.attributes[ 3 ][ 'value' ] = '{"t":"' + categoryString + categoryDelimiter + category + '"}';
|
769 |
+
} else {
|
770 |
+
this.mainCategory = categoryString;
|
771 |
+
this.attributes[ 3 ][ 'value' ] = '{"t":"' + categoryString + '"}';
|
772 |
+
}
|
773 |
+
}
|
774 |
+
}
|
775 |
+
}
|
776 |
+
}
|
777 |
+
|
778 |
+
function setSchedule( days, hours, minutes, frequency ) {
|
779 |
+
|
780 |
+
this.updateSchedule = days + ':' + hours + ':' + minutes + ':' + frequency;
|
781 |
+
}
|
782 |
+
|
783 |
+
function activateFeedsAttribute( attributeId ) {
|
784 |
+
|
785 |
+
this.attributes[ attributeId ][ 'isActive' ] = true;
|
786 |
+
}
|
787 |
+
|
788 |
+
function deactivateFeedsAttribute( attributeId ) {
|
789 |
+
|
790 |
+
if ( this.attributes[ attributeId ][ 'fieldLevel' ] !== '1' ) {
|
791 |
+
|
792 |
+
var attributeDataObject = this.attributes[ attributeId ][ 'value' ] ? JSON.parse( this.attributes[ attributeId ][ 'value' ] ) : {};
|
793 |
+
this.attributes[ attributeId ][ 'isActive' ] = false;
|
794 |
+
|
795 |
+
// clear the meta value but only if it not contains the category string
|
796 |
+
if ( attributeDataObject && ! 't' in attributeDataObject ) {
|
797 |
+
this.attributes[ attributeId ][ 'value' ] = '';
|
798 |
+
}
|
799 |
+
} else {
|
800 |
+
|
801 |
+
this.attributes[ attributeId ][ 'isActive' ] = true; // any required attribute should always stay active
|
802 |
+
}
|
803 |
+
}
|
804 |
+
|
805 |
+
function checkCustomName( name ) {
|
806 |
+
|
807 |
+
var result = false;
|
808 |
+
|
809 |
+
for ( var i = 0; i < this.attributes.length; i ++ ) {
|
810 |
+
|
811 |
+
if ( this.attributes[ i ][ 'fieldName' ] === name ) {
|
812 |
+
result = true;
|
813 |
+
}
|
814 |
+
}
|
815 |
+
|
816 |
+
return result;
|
817 |
+
}
|
818 |
+
|
819 |
+
function getFeedType() {
|
820 |
+
return this.feedType;
|
821 |
+
}
|
822 |
+
|
823 |
+
function removeAttribute( attributeId ) {
|
824 |
+
|
825 |
+
this.attributes.splice( attributeId, 1 );
|
826 |
+
}
|
827 |
+
|
828 |
+
function cleanUnusedAttributes() {
|
829 |
+
|
830 |
+
if ( this.attributes.length > 0 ) {
|
831 |
+
|
832 |
+
for ( var i = 0; i < this.attributes.length; i ++ ) {
|
833 |
+
|
834 |
+
if ( this.attributes[ i ][ 'isActive' ] !== true ) {
|
835 |
+
|
836 |
+
this.attributes.splice( i, 1 );
|
837 |
+
i --; // reset i for the removed attribute
|
838 |
+
} else if ( this.attributes[ i ][ 'advisedSource' ] === undefined && getSourceString( this.attributes[ i ][ 'value' ] ) === '' ) {
|
839 |
+
|
840 |
+
this.attributes.splice( i, 1 );
|
841 |
+
i --; // reset i for the removed attribute
|
842 |
+
}
|
843 |
+
}
|
844 |
+
}
|
845 |
+
}
|
846 |
+
|
847 |
+
function clearAttributes() {
|
848 |
+
this.attributes = [];
|
849 |
+
}
|
includes/application/js/tvc_object-feed.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
function Feed(e,n,g,d,j,k,o,c,a,f,i,b,m,q,p,h,l){this.feedId=e;this.title=n;this.mainCategory=k;this.categoryMapping=o;this.includeVariations=g;this.isAggregator=d;this.feedTitle=b;this.feedDescription=m;this.url=c;this.dataSource=a;this.channel=j;this.country=j!=="3"?f:"NL";this.language=i;this.status=h;this.updateSchedule=q;this.feedFilter=p;this.attributes=[];this.feedType=l;this.addAttribute=addAttributeToFeed;this.getAttributeIdByName=getAttributeId;this.activateAttribute=activateFeedsAttribute;this.checkIfCustomNameExists=checkCustomName;this.countCombinedFields=countAttributesCombinedFields;this.deactivateAttribute=deactivateFeedsAttribute;this.deactivateCategory=deactivateCategoryMap;this.activateCategory=activateCategoryMap;this.setStaticAttributeValue=setAttributesStaticValue;this.setSourceValue=setAttributesSourceValue;this.setAlternativeSourceValue=setAlternativeAttributesSourceValue;this.setCombinedOutputValue=setAttributesCombinedOutputValue;this.setCategoryValue=setAttributesCategoryValue;this.setFeedFilter=setFeedFilterValue;this.mapCategory=mapACategory;this.changeCustomFeedCategoryMap=changeCustomCategoryMap;this.changeIncludeVariations=changeIncludeVariationsValue;this.changeAggregator=changeAggregatorValue;this.resetNrQueries=rstNrQueries;this.incrNrQueries=addNrQueries;this.decrNrQueries=substrNrQueries;this.addConditionValue=addAttributesCondition;this.addValueQueryValue=addAttributesValueQuery;this.removeAttribute=removeAttributeFromFeed;this.removeValueConditionValue=removeAttributesCondition;this.removeValueQueryValue=removeAttributesValueQuery;this.removeAlternativeSourceValue=removeAlternativeSource;this.removeCombinedOutputValue=removeAttributesCombinedOutputValue;this.removeEditValueValue=removeAttributesEditValue;this.removeFeedFilter=removeFeedFilterValue;this.getAttributesQueriesObject=getAttributesQueries;this.getCombinedOutputValue=getAttributesCombinedOutputValue;this.getValueQueryValue=getAttributesValueQueries;this.getAttributesSourceObject=getAttributesSources;this.getSourceObject=getSourceData;this.getAlternativeSourcesObject=getAlternativeSources;this.getAttributesValueObject=getAttributesValues;this.getFeedFilter=getFeedFilterValue;this.getFeedType=getFeedType;this.setMainCategory=setCategories;this.setUpdateSchedule=setSchedule;this.setCustomCategory=setFeedCustomCategory;this.setCountry=changeCountry;this.clearSourceValue=clearAttributesSourceValue;this.cleanAttributes=cleanUnusedAttributes;this.clearAllAttributes=clearAttributes;this.addChangeValue=addAttributesChangeValue}function FeedAttribute(e,g,h,f,b,i,a,c,d){this.rowId=e;this.fieldName=g;this.advisedSource=h;this.value=f;this.fieldLevel=b;this.isActive=i;this.nrQueries=a;this.nrValueEdits=c;this.nrValueConditions=d}function CategoryMap(b,a){this.shopCategoryId=b;this.feedCategories=a}function addAttributeToFeed(e,h,i,g,b,j,d,c,f){var a=new FeedAttribute(e,h,i,g,b,j,d,c,f);this.attributes.push(a)}function removeAttributeFromFeed(b){for(var a=0;a<this.attributes.length;a++){if(this.attributes[a].rowId===b){this.attributes.splice(a,1)}}}function mapACategory(i,a){var h=i.match(/(\d+)$/)[0];var f=i.replace("_"+h,"");var b=f.match(/(\d+)$/)[0];var c=JSON.parse(this.categoryMapping);var d=jQuery.grep(c,function(j){return j.shopCategoryId===b});if(d.length>0){var e=d[0].feedCategories;d[0].feedCategories=tvc_addNewItemToCategoryString(h,e,a," > ")}else{var g=new CategoryMap();g.shopCategoryId=b;g.feedCategories=a;c.push(g)}this.categoryMapping=JSON.stringify(c)}function changeCustomCategoryMap(c,b){var d=JSON.parse(this.categoryMapping);var a=jQuery.grep(d,function(f){return f.shopCategoryId===c});if(a.length>0){a[0].feedCategories=b}else{var e=new CategoryMap();e.shopCategoryId=c;e.feedCategories=b;d.push(e)}this.categoryMapping=JSON.stringify(d)}function changeIncludeVariationsValue(a){this.includeVariations=a?"1":"0"}function changeAggregatorValue(a){this.isAggregator=a?"1":"0"}function activateCategoryMap(c,b){var d=this.categoryMapping.length>0?JSON.parse(this.categoryMapping):[];var a=jQuery.grep(d,function(f){return f.shopCategoryId===c.toString()});if(a.length<1){var e=new CategoryMap();e.shopCategoryId=c.toString();e.feedCategories=b?"wp_ownCategory":"wp_mainCategory";d.push(e);this.categoryMapping=JSON.stringify(d)}}function deactivateCategoryMap(b){var c=this.categoryMapping.length>0?JSON.parse(this.categoryMapping):[];if(c.length>1){var a=tvc_arrayObjectIndexOf(c,b.toString(),"shopCategoryId");c.splice(a,1);this.categoryMapping=JSON.stringify(c)}else{this.categoryMapping=[]}}function getAttributeId(a){var c=false;for(var b=0;b<this.attributes.length;b++){if(this.attributes[b]["fieldName"]===a){c=this.attributes[b]["rowId"];break}}if(c===false){c=this.attributes.length}return c}function setAttributesStaticValue(b,e,d,c){var a=this.attributes[b]["value"];this.attributes[b]["value"]=tvc_storeSourceValue(e,a,"static",c);this.attributes[b]["isActive"]=!!this.attributes[b]["value"]}function setAttributesSourceValue(b,c,d){var a=this.attributes[b]["value"];this.attributes[b]["value"]=tvc_storeSourceValue(c,a,"source",d)}function setAlternativeAttributesSourceValue(b,f,c){var a={};var d=[];if(this.attributes[b]["value"]){a=JSON.parse(this.attributes[b]["value"]);a.a=addOrRemoveValueInValueString(a.a,c,f,"add")}else{var e={};e[1]=c;d.push(e);a.a=d}this.attributes[b]["value"]=JSON.stringify(a)}function setAttributesCombinedOutputValue(b,c,d){var a=this.attributes[b]["value"];console.log(a);this.attributes[b]["value"]=tvc_storeCombinedValue(c,a,d)}function getAttributesCombinedOutputValue(a,b){var c=this.attributes[a]["value"]?JSON.parse(this.attributes[a]["value"]):{};if(c&&c.m&&c.m[b]&&c.m[b].s&&c.m[b].s.f){return c.m[b].s.f}else{return""}}function removeAttributesCombinedOutputValue(c,d,b){var a=this.attributes[c]["value"];this.attributes[c]["value"]=tvc_removeCombinedValue(d,b,a)}function countAttributesCombinedFields(b){if(this.attributes[b]["value"]){var a=JSON.parse(this.attributes[b]["value"]);if(a.hasOwnProperty("f")){return tvc_countObjectItems(a.f)}else{return 0}}else{return 0}}function setAttributesCategoryValue(b,c){var a=this.attributes[b]["value"];this.attributes[b]["value"]=tvc_storeSourceValue(0,a,"",c)}function rstNrQueries(a){this.attributes[a]["nrQueries"]=0}function addNrQueries(a){var b=this.attributes[a]["nrQueries"];this.attributes[a]["nrQueries"]=b+1}function substrNrQueries(a){var b=this.attributes[a]["nrQueries"];if(b>0){this.attributes[a]["nrQueries"]=b-1}}function addAttributesChangeValue(b,d,e,c){var a=this.attributes[b]["value"];this.attributes[b]["value"]=tvc_storeValueChange(d,e,c,"add",a)}function addAttributesCondition(d,c,e,a){var b=this.attributes[d]["value"];this.attributes[d]["value"]=tvc_storeConditionValue(e,a,b,c)}function addAttributesValueQuery(d,e,c,a){var b=this.attributes[d]["value"];this.attributes[d]["value"]=tvc_storeQueryValue(e,c,b,a)}function setFeedFilterValue(a){this.feedFilter=a}function removeFeedFilterValue(a){this.feedFilter=removeFeedFilterLevel(this.feedFilter,a)}function removeAttributesCondition(c,d,a){var b=this.attributes[c]["value"];this.attributes[c]["value"]=tvc_removeConditionValue(d,a,b)}function removeAttributesValueQuery(c,d,b){var a=this.attributes[c]["value"];this.attributes[c]["value"]=tvc_removeQueryValue(d,b,a)}function removeAttributesEditValue(b,c,d){var a=this.attributes[b]["value"];this.attributes[b]["value"]=tvc_removeEditValuesValue(c,d,a)}function removeAlternativeSource(b,c){var a={};if(this.attributes[b]["value"]){a=JSON.parse(this.attributes[b]["value"]);a.a=addOrRemoveValueInValueString(a.a,"",c,"remove");if(!a.a){delete a.a}this.attributes[b]["value"]=JSON.stringify(a)}}function getAttributesQueries(b,c){var e=this.attributes[b]["value"];var a={};if(e){var d=JSON.parse(e);if(d&&d.hasOwnProperty("m")&&d.m[c]&&d.m[c].hasOwnProperty("c")&&d.m[c].c.length>0){a=d.m[c].c}}return a}function getAttributesValueQueries(b,c){var e=this.attributes[b]["value"];var a={};if(e){var d=JSON.parse(e);if(d&&d.v&&d.v[c]&&d.v[c].hasOwnProperty("q")&&d.v[c].q.length>0){a=d.v[c].q}}return a}function getAttributesValues(b){var d=this.attributes[b]["value"];var a={};if(d){var c=JSON.parse(d);if(c&&"v" in c&&c.v.length>0){a=c.v}}return a}function getFeedFilterValue(a){}function getAlternativeSources(b){var d=this.attributes[b]["value"];var a={};if(d){var c=JSON.parse(d);if(c&&"a" in c&&c.a.length>0){a=c.a}}return a}function getSourceData(a){var c={};c.rowId=a;c.fieldName=this.attributes[a]["fieldName"];c.advisedSource=this.attributes[a]["advisedSource"];var d=this.attributes[a]["value"];if(d){var b=JSON.parse(d);c.mapping=b&&"m" in b?b.m:[];c.changeValues=b&&"v" in b?b.v:[];c.customCondition=!!(b&&"t" in b)}else{c.mapping=[];c.changeValues=[];c.customCondition=false}return c}function getAttributesSources(a){var d=this.attributes[a]["value"];var b={};if(d){var c=JSON.parse(d);if(c&&"s" in c){b=c.s}}return b}function addOrRemoveValueInValueString(b,d,g,e){var c=b?b:[];if(e==="add"){var f={};var a="";f[g]=d;if(c[g-1]&&"q" in c[g-1]){a=c[g-1]["q"]}if(g in f){c.splice(g-1,1)}if(a){f.q=a}c.push(f)}else{c.splice(g-1,1);c=tvc_resortObject(c)}if(tvc_countObjectItems(c)>0){return c}else{return""}}function clearAttributesSourceValue(a,b){if(this.attributes[a]["value"]){this.attributes[a]["value"]=tvc_storeSourceValue(b,this.attributes[a]["value"],"clear","")}else{this.attributes[a]["value"]=""}}function setFeedCustomCategory(b,a){console.log(this.attributes);console.log(a);this.mainCategory=a;var d=b?b:getCustomCategoryAttributeId(this.attributes,a);if(d){console.log(d);var c=this.attributes[d]["value"]?JSON.parse(this.attributes[d]["value"]):{};c.t=a;this.attributes[d]["value"]=JSON.stringify(c)}}function changeCountry(a){this.country=a}function getCustomCategoryAttributeId(a){for(var b=0;b<a.length;b++){console.log(a[b]);var c=a[b]["value"]?JSON.parse(a[b]["value"]):{};console.log(c);if(c.hasOwnProperty("t")){return b}}}function setCategories(a,b,e){if(this.attributes[3]!==undefined){var f=this.attributes[3]["value"]?JSON.parse(this.attributes[3]["value"]):{};var k=tvc_category_separator(e);var h=this.mainCategory;var c=this.attributes[3]["value"]!==undefined?h.split(k).length:0;var j=a.match(/(\d+)$/)[0];if(j==="0"){this.mainCategory=b;this.attributes[3]["value"]='{"t":"'+b+'"}'}else{if(c<=j){this.mainCategory+=k+b;this.attributes[3]["value"]='{"t":"'+f.t+k+b+'"}'}else{var g=0;for(var d=0;d<j;d++){g=h.indexOf(k,g+1)}h=h.substring(0,g);if(b!=="0"){this.mainCategory=h+k+b;this.attributes[3]["value"]='{"t":"'+h+k+b+'"}'}else{this.mainCategory=h;this.attributes[3]["value"]='{"t":"'+h+'"}'}}}}}function setSchedule(d,a,b,c){this.updateSchedule=d+":"+a+":"+b+":"+c}function activateFeedsAttribute(a){this.attributes[a]["isActive"]=true}function deactivateFeedsAttribute(a){if(this.attributes[a]["fieldLevel"]!=="1"){var b=this.attributes[a]["value"]?JSON.parse(this.attributes[a]["value"]):{};this.attributes[a]["isActive"]=false;if(b&&!"t" in b){this.attributes[a]["value"]=""}}else{this.attributes[a]["isActive"]=true}}function checkCustomName(b){var a=false;for(var c=0;c<this.attributes.length;c++){if(this.attributes[c]["fieldName"]===b){a=true}}return a}function getFeedType(){return this.feedType}function removeAttribute(a){this.attributes.splice(a,1)}function cleanUnusedAttributes(){if(this.attributes.length>0){for(var a=0;a<this.attributes.length;a++){if(this.attributes[a]["isActive"]!==true){this.attributes.splice(a,1);a--}else{if(this.attributes[a]["advisedSource"]===undefined&&getSourceString(this.attributes[a]["value"])===""){this.attributes.splice(a,1);a--}}}}}function clearAttributes(){this.attributes=[]};
|
includes/application/tvc-cron-functions.php
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* @package TVC Product Feed Manager/Application/Functions
|
4 |
+
* @version 1.3.0
|
5 |
+
*/
|
6 |
+
|
7 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
8 |
+
exit;
|
9 |
+
}
|
10 |
+
/**
|
11 |
+
* Activates the feed update schedules using Cron Jobs
|
12 |
+
*/
|
13 |
+
function tvc_update_feeds() {
|
14 |
+
// include the required WordPress files
|
15 |
+
require_once( ABSPATH . 'wp-load.php' );
|
16 |
+
require_once( ABSPATH . 'wp-admin/includes/admin.php' );
|
17 |
+
require_once( ABSPATH . 'wp-admin/includes/file.php' ); // required for using the file system
|
18 |
+
require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); // required to prevent a fatal error about not finding the is_plugin_active function
|
19 |
+
// include all product feed manager files
|
20 |
+
require_once( ENHANCAD_PLUGIN_DIR . 'includes/user-interface/tvc-messaging-functions.php' );
|
21 |
+
//require_once( ENHANCAD_PLUGIN_DIR . 'includes/tvc-wpincludes.php' );
|
22 |
+
//require_once( ENHANCAD_PLUGIN_DIR . 'includes/data/tvc-admin-functions.php' );
|
23 |
+
//require_once( ENHANCAD_PLUGIN_DIR . 'includes/user-interface/tvc-url-functions.php' );
|
24 |
+
//require_once( ENHANCAD_PLUGIN_DIR . 'includes/application/tvc-feed-processing-support.php' );
|
25 |
+
//require_once( ENHANCAD_PLUGIN_DIR . 'includes/application/tvc-feed-processor-functions.php' );
|
26 |
+
|
27 |
+
// WooCommerce needs to be installed and active
|
28 |
+
if ( ! tvc_wc_installed_and_active() ) {
|
29 |
+
tvc_write_log_file( 'Tried to start the auto update process but failed because WooCommerce is not installed.' );
|
30 |
+
exit;
|
31 |
+
}
|
32 |
+
|
33 |
+
// Feed Manager requires at least WooCommerce version 3.0.0
|
34 |
+
if ( ! tvc_wc_min_version_required() ) {
|
35 |
+
tvc_write_log_file( sprintf( 'Tried to start the auto update process but failed because WooCommerce is older than version %s', TVC_MIN_REQUIRED_WC_VERSION ) );
|
36 |
+
exit;
|
37 |
+
}
|
38 |
+
|
39 |
+
WC_Post_types::register_taxonomies(); // make sure the woocommerce taxonomies are loaded
|
40 |
+
WC_Post_types::register_post_types(); // make sure the woocommerce post types are loaded
|
41 |
+
|
42 |
+
// include all required classes
|
43 |
+
//include_classes();
|
44 |
+
//include_channels();
|
45 |
+
|
46 |
+
do_action( 'tvc_automatic_feed_processing_triggered' );
|
47 |
+
|
48 |
+
// update the database if required
|
49 |
+
tvc_check_db_version();
|
50 |
+
|
51 |
+
// start updating the active feeds
|
52 |
+
$tvc_schedules = new TVC_Schedules();
|
53 |
+
$tvc_schedules->update_active_feeds();
|
54 |
+
}
|
includes/application/tvc-feed-processing-support.php
ADDED
@@ -0,0 +1,1583 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* @package TVC Product Feed Manager/Application/Functions
|
5 |
+
* @version 1.4.0
|
6 |
+
*/
|
7 |
+
|
8 |
+
trait TVC_Processing_Support {
|
9 |
+
|
10 |
+
protected $_selected_number;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Returns the correct category for this specific product
|
14 |
+
*
|
15 |
+
* @param string $id
|
16 |
+
* @param string $main_category
|
17 |
+
* @param string $category_mapping
|
18 |
+
*
|
19 |
+
* @return string
|
20 |
+
*/
|
21 |
+
protected function get_mapped_category( $id, $main_category, $category_mapping ) {
|
22 |
+
$result = false;
|
23 |
+
$support_class = new TVC_Feed_Support();
|
24 |
+
$yoast_primary_category = TVC_Taxonomies::get_yoast_primary_cat( $id );
|
25 |
+
$yoast_cat_is_selected = $yoast_primary_category ? $support_class->category_is_selected( $yoast_primary_category[0]->term_id, $category_mapping ) : false;
|
26 |
+
|
27 |
+
$product_categories = $yoast_primary_category && false !== $yoast_cat_is_selected ? $yoast_primary_category :
|
28 |
+
wp_get_post_terms( $id, 'product_cat', array( 'taxonomy' => 'product_cat' ) ); // get the categories from a specific product in the shop
|
29 |
+
|
30 |
+
if ( $product_categories && ! is_wp_error( $product_categories ) ) {
|
31 |
+
// loop through each category
|
32 |
+
foreach ( $product_categories as $category ) {
|
33 |
+
// check if this category is selected in the category mapping
|
34 |
+
$shop_category_id = $support_class->category_is_selected( $category->term_id, $category_mapping );
|
35 |
+
|
36 |
+
// only add this product when at least one of the categories is selected in the category mapping
|
37 |
+
if ( false !== $shop_category_id ) {
|
38 |
+
switch ( $category_mapping[ $shop_category_id ]->feedCategories ) {
|
39 |
+
case 'wp_mainCategory':
|
40 |
+
$result = $main_category;
|
41 |
+
break;
|
42 |
+
|
43 |
+
case 'wp_ownCategory':
|
44 |
+
$result = TVC_Taxonomies::get_shop_categories( $id, ' > ' );
|
45 |
+
break;
|
46 |
+
|
47 |
+
default:
|
48 |
+
$result = $category_mapping[ $shop_category_id ]->feedCategories;
|
49 |
+
}
|
50 |
+
|
51 |
+
// found a selected category so now return the result
|
52 |
+
return $result; // fixed ticket #1117
|
53 |
+
|
54 |
+
} else { // if this product was not selected in the category mapping, it is possible it has been filtered in so map to the default category
|
55 |
+
$result = $main_category;
|
56 |
+
}
|
57 |
+
}
|
58 |
+
} else {
|
59 |
+
if ( is_wp_error( $product_categories ) ) {
|
60 |
+
echo tvc_handle_wp_errors_response(
|
61 |
+
$product_categories,
|
62 |
+
sprintf(
|
63 |
+
/* translators: %s: link to the support page */
|
64 |
+
esc_html__( '2131 - Please try to refresh the page and open a support ticket at %s if the issue persists.', 'tvc-product-feed-manager'),
|
65 |
+
TVC_SUPPORT_PAGE_URL
|
66 |
+
)
|
67 |
+
);
|
68 |
+
}
|
69 |
+
|
70 |
+
return false;
|
71 |
+
}
|
72 |
+
|
73 |
+
return $result;
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Checks if this product has been filtered out of the feed
|
78 |
+
*
|
79 |
+
* @param string $feed_filter_strings
|
80 |
+
* @param array $product_data
|
81 |
+
*
|
82 |
+
* @return boolean
|
83 |
+
*/
|
84 |
+
protected function is_product_filtered( $feed_filter_strings, $product_data ) {
|
85 |
+
if ( $feed_filter_strings ) {
|
86 |
+
return $this->filter_result( json_decode( $feed_filter_strings[0]['meta_value'] ), $product_data ) ? true : false;
|
87 |
+
} else {
|
88 |
+
return false;
|
89 |
+
}
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* @param $feed_id
|
94 |
+
* @return array
|
95 |
+
*/
|
96 |
+
protected function get_meta_parent_ids( $feed_id ) {
|
97 |
+
$queries_class = new TVC_Queries();
|
98 |
+
|
99 |
+
$query_result = $queries_class->get_meta_parents( $feed_id );
|
100 |
+
$ids = array();
|
101 |
+
|
102 |
+
foreach ( $query_result as $result ) {
|
103 |
+
array_push( $ids, $result['ID'] );
|
104 |
+
}
|
105 |
+
|
106 |
+
return $ids;
|
107 |
+
}
|
108 |
+
|
109 |
+
/**
|
110 |
+
* return an array with source column names from an attribute string
|
111 |
+
*
|
112 |
+
* @param string $value_string
|
113 |
+
*
|
114 |
+
* @return array
|
115 |
+
*/
|
116 |
+
protected function get_source_columns_from_attribute_value( $value_string ) {
|
117 |
+
$source_columns = array();
|
118 |
+
|
119 |
+
$value_object = json_decode( $value_string );
|
120 |
+
|
121 |
+
if ( property_exists( $value_object, 'm' ) ) {
|
122 |
+
foreach ( $value_object->m as $source ) {
|
123 |
+
// TODO: I guess I should further reduce the "if" loops by combining them more then now
|
124 |
+
if ( is_object( $source ) && property_exists( $source, 's' ) ) {
|
125 |
+
if ( property_exists( $source->s, 'source' ) ) {
|
126 |
+
if ( 'combined' !== $source->s->source ) {
|
127 |
+
array_push( $source_columns, $source->s->source );
|
128 |
+
} else {
|
129 |
+
if ( property_exists( $source->s, 'f' ) ) {
|
130 |
+
$source_columns = array_merge( $source_columns, $this->get_combined_sources_from_combined_string( $source->s->f ) );
|
131 |
+
}
|
132 |
+
}
|
133 |
+
}
|
134 |
+
}
|
135 |
+
}
|
136 |
+
}
|
137 |
+
return $source_columns;
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* return an array with condition column names from an attribute string
|
142 |
+
*
|
143 |
+
* @param string $value_string
|
144 |
+
*
|
145 |
+
* @return array
|
146 |
+
*/
|
147 |
+
protected function get_condition_columns_from_attribute_value( $value_string ) {
|
148 |
+
$condition_columns = array();
|
149 |
+
|
150 |
+
$value_object = json_decode( $value_string );
|
151 |
+
|
152 |
+
if ( property_exists( $value_object, 'm' ) ) {
|
153 |
+
foreach ( $value_object->m as $source ) {
|
154 |
+
if ( is_object( $source ) && property_exists( $source, 'c' ) ) {
|
155 |
+
for ( $i = 0; $i < count( $source->c ); $i ++ ) {
|
156 |
+
array_push( $condition_columns, $this->get_names_from_string( $source->c[ $i ]->{$i + 1} ) );
|
157 |
+
}
|
158 |
+
}
|
159 |
+
}
|
160 |
+
}
|
161 |
+
return $condition_columns;
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* return an array with query column names from an attribute string
|
166 |
+
*
|
167 |
+
* @param string $value_string
|
168 |
+
*
|
169 |
+
* @return array
|
170 |
+
*/
|
171 |
+
protected function get_queries_columns_from_attribute_value( $value_string ) {
|
172 |
+
$query_columns = array();
|
173 |
+
|
174 |
+
$value_object = json_decode( $value_string );
|
175 |
+
|
176 |
+
if ( property_exists( $value_object, 'v' ) ) {
|
177 |
+
foreach ( $value_object->v as $changed_value ) {
|
178 |
+
if ( property_exists( $changed_value, 'q' ) ) {
|
179 |
+
for ( $i = 0; $i < count( $changed_value->q ); $i ++ ) {
|
180 |
+
array_push( $query_columns, $this->get_names_from_string( $changed_value->q[ $i ]->{$i + 1} ) );
|
181 |
+
}
|
182 |
+
}
|
183 |
+
}
|
184 |
+
}
|
185 |
+
return $query_columns;
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* extract a column name from a string
|
190 |
+
*
|
191 |
+
* @param string $string
|
192 |
+
*
|
193 |
+
* @return array
|
194 |
+
*/
|
195 |
+
protected function get_names_from_string( $string ) {
|
196 |
+
$condition_string_array = explode( '#', $string );
|
197 |
+
|
198 |
+
return $condition_string_array[1];
|
199 |
+
}
|
200 |
+
|
201 |
+
/**
|
202 |
+
* split the combined string into single combination items
|
203 |
+
*
|
204 |
+
* @param string $combined_string
|
205 |
+
*
|
206 |
+
* @return array
|
207 |
+
*/
|
208 |
+
public function get_combined_sources_from_combined_string( $combined_string ) {
|
209 |
+
$result = array();
|
210 |
+
$combined_string_array = explode( '|', $combined_string );
|
211 |
+
|
212 |
+
array_push( $result, $combined_string_array[0] );
|
213 |
+
|
214 |
+
for ( $i = 1; $i < count( $combined_string_array ); $i ++ ) {
|
215 |
+
$a = explode( '#', $combined_string_array[ $i ] );
|
216 |
+
if ( array_key_exists( 1, $a ) ) {
|
217 |
+
array_push( $result, $a[1] );
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
return $result;
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* Gets the meta data from a specific field
|
226 |
+
*
|
227 |
+
* @param string $field
|
228 |
+
* @param stdClass $attributes
|
229 |
+
*
|
230 |
+
* @return stdClass attribute
|
231 |
+
*/
|
232 |
+
protected function get_meta_data_from_specific_field( $field, $attributes ) {
|
233 |
+
$i = 0;
|
234 |
+
|
235 |
+
while ( true ) {
|
236 |
+
if ( $attributes[ $i ]->fieldName !== $field ) {
|
237 |
+
$i ++;
|
238 |
+
if ( $i > 1000 ) {
|
239 |
+
break;
|
240 |
+
}
|
241 |
+
} else {
|
242 |
+
return $attributes[ $i ];
|
243 |
+
}
|
244 |
+
}
|
245 |
+
|
246 |
+
return new stdClass();
|
247 |
+
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* Generate the value of a field based on what the user has selected in filters, combined data, static data eg.
|
251 |
+
*
|
252 |
+
* @param array $product_data
|
253 |
+
* @param stdClass $field_meta_data
|
254 |
+
* @param string $main_category_feed_title
|
255 |
+
* @param string $row_category
|
256 |
+
* @param string $feed_language
|
257 |
+
* @param array $relation_table
|
258 |
+
*
|
259 |
+
* @return array Returns an key=>value array of a specific product field where the key contains the field name and the value the field value
|
260 |
+
*/
|
261 |
+
protected function process_product_field( $product_data, $field_meta_data, $main_category_feed_title, $row_category, $feed_language, $relation_table ) {
|
262 |
+
|
263 |
+
$product_object[ $field_meta_data->fieldName ] = $this->get_correct_field_value(
|
264 |
+
$field_meta_data,
|
265 |
+
$product_data,
|
266 |
+
$main_category_feed_title,
|
267 |
+
$row_category,
|
268 |
+
$feed_language,
|
269 |
+
$relation_table
|
270 |
+
);
|
271 |
+
|
272 |
+
return $product_object;
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* Processes a single field of a single product in the feed
|
277 |
+
*
|
278 |
+
* @param stdClass $field_meta_data containing the meta data of the field
|
279 |
+
* @param array $product_data containing the product data of the field
|
280 |
+
* @param string $main_category_feed_title main category title
|
281 |
+
* @param string $row_category complete category string
|
282 |
+
* @param string $feed_language language of the feed
|
283 |
+
* @param array $relation_table table with the shop and merchant category relations
|
284 |
+
*
|
285 |
+
* @return string
|
286 |
+
*/
|
287 |
+
protected function get_correct_field_value( $field_meta_data, $product_data, $main_category_feed_title, $row_category, $feed_language, $relation_table ) {
|
288 |
+
$this->_selected_number = 0;
|
289 |
+
|
290 |
+
// do not process category strings, but only fields that are requested
|
291 |
+
if ( property_exists( $field_meta_data, 'fieldName' ) && $field_meta_data->fieldName !== $main_category_feed_title
|
292 |
+
&& $this->meta_data_contains_category_data( $field_meta_data ) === false ) {
|
293 |
+
|
294 |
+
$value_object = property_exists( $field_meta_data, 'value' ) && '' !== $field_meta_data->value ? json_decode( $field_meta_data->value ) : new stdClass();
|
295 |
+
|
296 |
+
if ( property_exists( $field_meta_data, 'value' ) && '' !== $field_meta_data->value && property_exists( $value_object, 'm' ) ) { // seems to be something we need to work on
|
297 |
+
$advised_source = property_exists( $field_meta_data, 'advisedSource' ) ? $field_meta_data->advisedSource : '';
|
298 |
+
|
299 |
+
// get the end value depending on the filter settings
|
300 |
+
$end_row_value = $this->get_correct_end_row_value( $value_object->m, $product_data, $advised_source );
|
301 |
+
|
302 |
+
} else { // no queries, edit values or alternative sources for this field
|
303 |
+
|
304 |
+
if ( property_exists( $field_meta_data, 'advisedSource' ) && '' !== $field_meta_data->advisedSource ) {
|
305 |
+
$db_title = $field_meta_data->advisedSource;
|
306 |
+
} else {
|
307 |
+
$support_class = new TVC_Feed_Support();
|
308 |
+
$source_title = property_exists( $field_meta_data, 'fieldName' ) ? $field_meta_data->fieldName : '';
|
309 |
+
$db_title = $support_class->find_relation( $source_title, $relation_table );
|
310 |
+
}
|
311 |
+
|
312 |
+
$end_row_value = array_key_exists( $db_title, $product_data ) ? $product_data[ $db_title ] : '';
|
313 |
+
}
|
314 |
+
|
315 |
+
// change value if requested
|
316 |
+
if ( property_exists( $field_meta_data, 'value' ) && '' !== $field_meta_data->value && property_exists( $value_object, 'v' ) ) {
|
317 |
+
$pos = $this->_selected_number;
|
318 |
+
|
319 |
+
if ( property_exists( $value_object, 'm' ) && property_exists( $value_object->m[ $pos ], 's' ) ) {
|
320 |
+
$combination_string = property_exists( $value_object->m[ $pos ]->s, 'f' ) ? $value_object->m[ $pos ]->s->f : false;
|
321 |
+
$is_money = property_exists( $value_object->m[ $pos ]->s, 'source' ) ? tvc_meta_key_is_money( $value_object->m[ $pos ]->s->source ) : false;
|
322 |
+
} else {
|
323 |
+
$combination_string = false;
|
324 |
+
$is_money = false;
|
325 |
+
}
|
326 |
+
|
327 |
+
$row_value = ! $is_money ? $end_row_value : tvc_prep_money_values( $end_row_value . $feed_language );
|
328 |
+
$end_row_value = $this->get_edited_end_row_value( $value_object->v, $row_value, $product_data, $combination_string, $feed_language );
|
329 |
+
}
|
330 |
+
} else {
|
331 |
+
$end_row_value = $row_category;
|
332 |
+
}
|
333 |
+
|
334 |
+
return $end_row_value;
|
335 |
+
}
|
336 |
+
|
337 |
+
/**
|
338 |
+
* @param $value
|
339 |
+
* @param $product_data
|
340 |
+
* @param $advised_source
|
341 |
+
* @return array|mixed|string
|
342 |
+
*/
|
343 |
+
protected function get_correct_end_row_value( $value, $product_data, $advised_source ) {
|
344 |
+
$end_row_value = '';
|
345 |
+
$nr_values = count( $value ); // added @since 1.9.4
|
346 |
+
$value_counter = 1; // added @since 1.9.4
|
347 |
+
|
348 |
+
foreach ( $value as $filter ) {
|
349 |
+
if ( true === $this->get_filter_status( $filter, $product_data ) && '' === $end_row_value ) {
|
350 |
+
|
351 |
+
$end_row_value = $this->get_row_source_data( $filter, $product_data, $advised_source );
|
352 |
+
break;
|
353 |
+
} else {
|
354 |
+
// no "or else" value seems to be selected
|
355 |
+
if ( $value_counter >= $nr_values ) {
|
356 |
+
return $end_row_value;
|
357 |
+
} // added @since 1.9.4
|
358 |
+
|
359 |
+
$this->_selected_number ++;
|
360 |
+
}
|
361 |
+
|
362 |
+
$value_counter ++; // added @since 1.9.4
|
363 |
+
}
|
364 |
+
|
365 |
+
// not found a condition that was correct so lets take the "for all other products" data to fetch the correct row_value
|
366 |
+
if ( '' === $end_row_value ) {
|
367 |
+
$end_row_value = $this->get_row_source_data( end( $value ), $product_data, $advised_source );
|
368 |
+
}
|
369 |
+
|
370 |
+
return $end_row_value;
|
371 |
+
}
|
372 |
+
|
373 |
+
/**
|
374 |
+
* Removes links from a the post content and post excerpts in a product data array.
|
375 |
+
*
|
376 |
+
* @since 2.6.0
|
377 |
+
*
|
378 |
+
* @param $product_data array
|
379 |
+
*/
|
380 |
+
protected function remove_links_from_product_data_description( &$product_data ) {
|
381 |
+
$pattern = '#<a.*?>(.*?)</a>#i'; // link pattern
|
382 |
+
$replacement = '\1';
|
383 |
+
|
384 |
+
if ( array_key_exists( 'post_content', $product_data ) ) {
|
385 |
+
$product_data['post_content'] = preg_replace( $pattern, $replacement, $product_data['post_content'] );
|
386 |
+
}
|
387 |
+
|
388 |
+
if ( array_key_exists( 'post_excerpt', $product_data ) ) {
|
389 |
+
$product_data['post_excerpt'] = preg_replace( $pattern, $replacement, $product_data['post_excerpt'] );
|
390 |
+
}
|
391 |
+
}
|
392 |
+
|
393 |
+
/**
|
394 |
+
* @param $filter
|
395 |
+
* @param $product_data
|
396 |
+
* @return bool
|
397 |
+
*/
|
398 |
+
protected function get_filter_status( $filter, $product_data ) {
|
399 |
+
if ( property_exists( $filter, 'c' ) ) {
|
400 |
+
// check if the query is true for this field
|
401 |
+
return $this->filter_result( $filter->c, $product_data );
|
402 |
+
} else {
|
403 |
+
// apparently there is no condition so the result is always true
|
404 |
+
return true;
|
405 |
+
}
|
406 |
+
}
|
407 |
+
|
408 |
+
/**
|
409 |
+
* @param $conditions
|
410 |
+
* @param $product_data
|
411 |
+
* @return bool
|
412 |
+
*/
|
413 |
+
protected function filter_result( $conditions, $product_data ) {
|
414 |
+
$query_results = array();
|
415 |
+
$support_class = new TVC_Feed_Support();
|
416 |
+
|
417 |
+
// run each query on the data
|
418 |
+
foreach ( $conditions as $condition ) {
|
419 |
+
$condition_string = $support_class->get_query_string_from_query_object( $condition );
|
420 |
+
|
421 |
+
$query_split = explode( '#', $condition_string );
|
422 |
+
|
423 |
+
$row_result = $support_class->check_query_result_on_specific_row( $query_split, $product_data ) === true ? 'false' : 'true';
|
424 |
+
|
425 |
+
array_push( $query_results, $query_split[0] . '#' . $row_result );
|
426 |
+
}
|
427 |
+
|
428 |
+
// return the final filter result, based on the specific results
|
429 |
+
return $this->connect_query_results( $query_results );
|
430 |
+
}
|
431 |
+
|
432 |
+
/**
|
433 |
+
* Recieves an array with condition results and generates a single end result based on the "and" or "or"
|
434 |
+
* connection between the conditions
|
435 |
+
*
|
436 |
+
* @param array with $results
|
437 |
+
*
|
438 |
+
* @return boolean
|
439 |
+
*/
|
440 |
+
protected function connect_query_results( $results ) {
|
441 |
+
$and_results = array();
|
442 |
+
$end_result = true;
|
443 |
+
$or_results = array();
|
444 |
+
|
445 |
+
if ( count( $results ) > 0 ) {
|
446 |
+
foreach ( $results as $query_result ) {
|
447 |
+
$result_split = explode( '#', $query_result );
|
448 |
+
|
449 |
+
if ( '2' === $result_split[0] ) {
|
450 |
+
array_push( $or_results, $and_results ); // store the current "and" result for processing as "or" result
|
451 |
+
|
452 |
+
$and_results = array(); // clear the "and" array
|
453 |
+
}
|
454 |
+
|
455 |
+
$and_result = $result_split[1]; // === 'false' ? 'false' : 'true';
|
456 |
+
|
457 |
+
array_push( $and_results, $and_result );
|
458 |
+
}
|
459 |
+
|
460 |
+
if ( count( $and_results ) > 0 ) {
|
461 |
+
array_push( $or_results, $and_results );
|
462 |
+
}
|
463 |
+
|
464 |
+
if ( count( $or_results ) > 0 ) {
|
465 |
+
$end_result = false;
|
466 |
+
|
467 |
+
foreach ( $or_results as $or_result ) {
|
468 |
+
$a = true;
|
469 |
+
|
470 |
+
foreach ( $or_result as $and_array ) {
|
471 |
+
if ( 'false' === $and_array ) {
|
472 |
+
$a = false;
|
473 |
+
}
|
474 |
+
}
|
475 |
+
|
476 |
+
if ( $a ) {
|
477 |
+
$end_result = true;
|
478 |
+
}
|
479 |
+
}
|
480 |
+
} else { // no "or" results found
|
481 |
+
$end_result = false;
|
482 |
+
}
|
483 |
+
} else {
|
484 |
+
$end_result = false;
|
485 |
+
}
|
486 |
+
|
487 |
+
return $end_result;
|
488 |
+
}
|
489 |
+
|
490 |
+
/**
|
491 |
+
* @param $filter
|
492 |
+
* @param $product_data
|
493 |
+
* @param $advised_source
|
494 |
+
* @return array|mixed|string
|
495 |
+
*/
|
496 |
+
protected function get_row_source_data( $filter, $product_data, $advised_source ) {
|
497 |
+
$row_source_data = '';
|
498 |
+
|
499 |
+
if ( property_exists( $filter, 's' ) ) {
|
500 |
+
if ( property_exists( $filter->s, 'static' ) ) {
|
501 |
+
$row_source_data = $filter->s->static;
|
502 |
+
} elseif ( property_exists( $filter->s, 'source' ) ) {
|
503 |
+
if ( 'combined' !== $filter->s->source ) {
|
504 |
+
$row_source_data = array_key_exists( $filter->s->source, $product_data ) ? $product_data[ $filter->s->source ] : '';
|
505 |
+
} else {
|
506 |
+
$row_source_data = $this->generate_combined_string( $filter->s->f, $product_data );
|
507 |
+
}
|
508 |
+
}
|
509 |
+
} else {
|
510 |
+
// return the advised source data
|
511 |
+
if ( '' !== $advised_source ) {
|
512 |
+
$row_source_data = array_key_exists( $advised_source, $product_data ) ? $product_data[ $advised_source ] : '';
|
513 |
+
}
|
514 |
+
}
|
515 |
+
|
516 |
+
return $row_source_data;
|
517 |
+
}
|
518 |
+
|
519 |
+
/**
|
520 |
+
* @param $combined_sources
|
521 |
+
* @param $row
|
522 |
+
* @return array|string
|
523 |
+
*/
|
524 |
+
protected function generate_combined_string( $combined_sources, $row ) {
|
525 |
+
$source_selectors_array = explode( '|', $combined_sources ); //split the combined source string in an array containing every single source
|
526 |
+
$values_class = new TVC_Feed_Value_Editors();
|
527 |
+
$separators = $values_class->combination_separators(); // array with all possible separators
|
528 |
+
|
529 |
+
// if one of the row results is an array, the final output needs to be an array
|
530 |
+
$result_is_array = $this->check_if_any_source_has_array_data( $source_selectors_array, $row );
|
531 |
+
$result = $result_is_array ? array() : '';
|
532 |
+
|
533 |
+
if ( ! $result_is_array ) {
|
534 |
+
$result = $this->make_combined_string( $source_selectors_array, $separators, $row, false );
|
535 |
+
} else {
|
536 |
+
for ( $i = 0; $i < count( $result_is_array ); $i ++ ) {
|
537 |
+
$combined_string = $this->make_combined_string( $source_selectors_array, $separators, $row, $i );
|
538 |
+
array_push( $result, $combined_string );
|
539 |
+
}
|
540 |
+
}
|
541 |
+
|
542 |
+
return $result;
|
543 |
+
}
|
544 |
+
|
545 |
+
/**
|
546 |
+
* Distracts the keys from the $sources string (separated by a #) and looks if any of these keys
|
547 |
+
* are linked to an array in the $data_row
|
548 |
+
*
|
549 |
+
* @param array $sources
|
550 |
+
* @param array $data_row
|
551 |
+
*
|
552 |
+
* @return array|bool from the data_row or false
|
553 |
+
*/
|
554 |
+
protected function check_if_any_source_has_array_data( $sources, $data_row ) {
|
555 |
+
foreach ( $sources as $source ) {
|
556 |
+
$split_source = explode( '#', $source );
|
557 |
+
|
558 |
+
if ( count( $split_source ) > 1 && 'static' === $split_source[1] ) {
|
559 |
+
$last_key = 'static';
|
560 |
+
} elseif ( 'static' === $split_source[0] ) {
|
561 |
+
$last_key = 'static';
|
562 |
+
} else {
|
563 |
+
$last_key = array_pop( $split_source );
|
564 |
+
}
|
565 |
+
|
566 |
+
if ( array_key_exists( $last_key, $data_row ) && is_array( $data_row[ $last_key ] ) ) {
|
567 |
+
return $data_row[ $last_key ];
|
568 |
+
}
|
569 |
+
}
|
570 |
+
|
571 |
+
return false;
|
572 |
+
}
|
573 |
+
|
574 |
+
/**
|
575 |
+
* @param $meta_data
|
576 |
+
* @return bool
|
577 |
+
*/
|
578 |
+
protected function meta_data_contains_category_data( $meta_data ) {
|
579 |
+
if ( ! property_exists( $meta_data, 'value' ) || empty( $meta_data->value ) ) {
|
580 |
+
return false;
|
581 |
+
}
|
582 |
+
|
583 |
+
$meta_obj = json_decode( $meta_data->value );
|
584 |
+
|
585 |
+
return property_exists( $meta_obj, 't' ) ? true : false;
|
586 |
+
}
|
587 |
+
|
588 |
+
/**
|
589 |
+
* @param $change_parameters
|
590 |
+
* @param $original_output
|
591 |
+
* @param $product_data
|
592 |
+
* @param $combination_string
|
593 |
+
* @param $feed_language
|
594 |
+
* @return float|int|mixed|string
|
595 |
+
*/
|
596 |
+
protected function get_edited_end_row_value( $change_parameters, $original_output, $product_data, $combination_string, $feed_language ) {
|
597 |
+
$result_is_filtered = false;
|
598 |
+
$support_class = new TVC_Feed_Support();
|
599 |
+
$y = 0;
|
600 |
+
$final_output = '';
|
601 |
+
|
602 |
+
for ( $i = 0; $i < ( count( $change_parameters ) - 1 ); $i ++ ) {
|
603 |
+
if ( property_exists( $change_parameters[ $i ], 'q' ) ) {
|
604 |
+
$filter_result = $this->filter_result( $change_parameters[ $i ]->q, $product_data );
|
605 |
+
|
606 |
+
if ( true === $filter_result ) {
|
607 |
+
$combined_data_elements = $combination_string ? $this->get_combined_elements( $product_data, $combination_string ) : '';
|
608 |
+
$final_output = $support_class->edit_value(
|
609 |
+
$original_output,
|
610 |
+
$change_parameters[ $i ]->{$i + 1},
|
611 |
+
$combination_string,
|
612 |
+
$combined_data_elements,
|
613 |
+
$feed_language
|
614 |
+
);
|
615 |
+
|
616 |
+
$result_is_filtered = true;
|
617 |
+
}
|
618 |
+
}
|
619 |
+
|
620 |
+
$y ++;
|
621 |
+
}
|
622 |
+
|
623 |
+
if ( false === $result_is_filtered ) {
|
624 |
+
$combined_data_elements = $combination_string ? $this->get_combined_elements( $product_data, $combination_string ) : '';
|
625 |
+
$final_output = $support_class->edit_value(
|
626 |
+
$original_output,
|
627 |
+
$change_parameters[ $y ]->{$y + 1},
|
628 |
+
$combination_string,
|
629 |
+
$combined_data_elements,
|
630 |
+
$feed_language
|
631 |
+
);
|
632 |
+
}
|
633 |
+
|
634 |
+
return $final_output;
|
635 |
+
}
|
636 |
+
|
637 |
+
/**
|
638 |
+
* @param $product_data
|
639 |
+
* @param $combination_string
|
640 |
+
* @return array
|
641 |
+
*/
|
642 |
+
protected function get_combined_elements( $product_data, $combination_string ) {
|
643 |
+
$result = array();
|
644 |
+
$found_all_data = true;
|
645 |
+
|
646 |
+
$combination_elements = explode( '|', $combination_string );
|
647 |
+
|
648 |
+
if ( false === strpos( $combination_elements[0], 'static#' ) ) {
|
649 |
+
if ( array_key_exists( $combination_elements[0], $product_data ) ) {
|
650 |
+
array_push( $result, $product_data[ $combination_elements[0] ] );
|
651 |
+
} else {
|
652 |
+
$found_all_data = false;
|
653 |
+
}
|
654 |
+
} else {
|
655 |
+
$element = explode( '#', $combination_elements[0] );
|
656 |
+
array_push( $result, $element[1] );
|
657 |
+
}
|
658 |
+
|
659 |
+
for ( $i = 1; $i <= count( $combination_elements ) - 1; $i ++ ) {
|
660 |
+
$pos = strpos( $combination_elements[ $i ], '#' );
|
661 |
+
$selector = substr( $combination_elements[ $i ], ( false !== $pos ? $pos + 1 : 0 ) );
|
662 |
+
|
663 |
+
if ( substr( $selector, 0, 7 ) === 'static#' ) {
|
664 |
+
$selector = explode( '#', $selector );
|
665 |
+
array_push( $result, $selector[1] );
|
666 |
+
} elseif ( array_key_exists( $selector, $product_data ) ) {
|
667 |
+
array_push( $result, $product_data[ $selector ] );
|
668 |
+
} else {
|
669 |
+
//array_push( $result, $selector );
|
670 |
+
$found_all_data = false;
|
671 |
+
}
|
672 |
+
}
|
673 |
+
|
674 |
+
if ( $found_all_data ) {
|
675 |
+
return $result;
|
676 |
+
} else {
|
677 |
+
$message = sprintf( 'Missing the data for one or both combined elements of the combination %s in the product with id %s.', $combination_string, $product_data['ID'] );
|
678 |
+
do_action( 'tvc_feed_generation_message', $this->_feed_data->feedId, $message );
|
679 |
+
return array();
|
680 |
+
}
|
681 |
+
}
|
682 |
+
|
683 |
+
/**
|
684 |
+
* @param $source_selectors_array
|
685 |
+
* @param $separators
|
686 |
+
* @param $row
|
687 |
+
* @param $array_pos
|
688 |
+
* @return string
|
689 |
+
*/
|
690 |
+
protected function make_combined_string( $source_selectors_array, $separators, $row, $array_pos ) {
|
691 |
+
$combined_string = '';
|
692 |
+
|
693 |
+
foreach ( $source_selectors_array as $source ) {
|
694 |
+
$split_source = explode( '#', $source );
|
695 |
+
|
696 |
+
// get the separator
|
697 |
+
$separators_id = count( $split_source ) > 1 && 'static' !== $split_source[0] ? $split_source[0] : 0;
|
698 |
+
$sep = $separators[ $separators_id ];
|
699 |
+
|
700 |
+
$data_key = count( $split_source ) > 1 && 'static' !== $split_source[0] ? $split_source[1] : $split_source[0];
|
701 |
+
|
702 |
+
if ( ( array_key_exists( $data_key, $row ) && $row[ $data_key ] ) || 'static' === $data_key ) {
|
703 |
+
if ( 'static' !== $data_key && ! is_array( $row[ $data_key ] ) ) { // not static and no array
|
704 |
+
$combined_string .= $sep;
|
705 |
+
$combined_string .= 'static' !== $data_key ? $row[ $data_key ] : $split_source[2];
|
706 |
+
} elseif ( 'static' === $data_key ) { // static inputs
|
707 |
+
$static_string = count( $split_source ) > 2 ? $split_source[2] : $split_source[1];
|
708 |
+
$combined_string .= $sep . $static_string;
|
709 |
+
} else { // array inputs
|
710 |
+
$input_array = $row[ $data_key ][ $array_pos ];
|
711 |
+
$combined_string .= $sep . $input_array;
|
712 |
+
}
|
713 |
+
}
|
714 |
+
}
|
715 |
+
|
716 |
+
return $combined_string;
|
717 |
+
}
|
718 |
+
|
719 |
+
/**
|
720 |
+
* get an array with the relations between the WooCommerce fields and the channel fields
|
721 |
+
*
|
722 |
+
* @return array
|
723 |
+
*/
|
724 |
+
public function get_channel_to_woocommerce_field_relations() {
|
725 |
+
$relations = array();
|
726 |
+
|
727 |
+
foreach ( $this->_feed->attributes as $attribute ) {
|
728 |
+
|
729 |
+
// get the source name except for the category_mapping field
|
730 |
+
if ( 'category_mapping' !== $attribute->fieldName ) {
|
731 |
+
$source = $this->get_source_from_attribute( $attribute );
|
732 |
+
}
|
733 |
+
|
734 |
+
if ( ! empty( $source ) ) {
|
735 |
+
// correct Google product category source
|
736 |
+
if ( 'google_product_category' === $attribute->fieldName ) {
|
737 |
+
$source = 'google_product_category';
|
738 |
+
}
|
739 |
+
|
740 |
+
// correct Google identifier exists source
|
741 |
+
if ( 'identifier_exists' === $attribute->fieldName ) {
|
742 |
+
$source = 'identifier_exists';
|
743 |
+
}
|
744 |
+
|
745 |
+
// fill the relations array
|
746 |
+
$a = array(
|
747 |
+
'field' => $attribute->fieldName,
|
748 |
+
'db' => $source,
|
749 |
+
);
|
750 |
+
array_push( $relations, $a );
|
751 |
+
}
|
752 |
+
}
|
753 |
+
|
754 |
+
if ( empty( $relations ) ) {
|
755 |
+
tvc_write_log_file( 'Function get_channel_to_woocommerce_field_relations returned zero relations.' );
|
756 |
+
}
|
757 |
+
|
758 |
+
return $relations;
|
759 |
+
}
|
760 |
+
|
761 |
+
/**
|
762 |
+
* extract the source name from the attribute string
|
763 |
+
*
|
764 |
+
* @param array $attribute
|
765 |
+
*
|
766 |
+
* @return string
|
767 |
+
*/
|
768 |
+
protected function get_source_from_attribute( $attribute ) {
|
769 |
+
|
770 |
+
$value_source = property_exists( $attribute, 'value' ) ? $this->get_source_from_attribute_value( $attribute->value ) : '';
|
771 |
+
|
772 |
+
if ( ! empty( $value_source ) ) {
|
773 |
+
$source = $value_source;
|
774 |
+
} elseif ( property_exists( $attribute, 'advisedSource' ) && '' !== $attribute->advisedSource ) {
|
775 |
+
$source = $attribute->advisedSource;
|
776 |
+
} else {
|
777 |
+
$source = $attribute->fieldName;
|
778 |
+
}
|
779 |
+
|
780 |
+
return $source;
|
781 |
+
}
|
782 |
+
|
783 |
+
/**
|
784 |
+
* extract the source value from the attribute string
|
785 |
+
*
|
786 |
+
* @param string $value
|
787 |
+
*
|
788 |
+
* @return string
|
789 |
+
*/
|
790 |
+
protected function get_source_from_attribute_value( $value ) {
|
791 |
+
$source = '';
|
792 |
+
|
793 |
+
if ( $value ) {
|
794 |
+
$value_string = $this->get_source_string( $value );
|
795 |
+
|
796 |
+
$value_object = json_decode( $value_string );
|
797 |
+
|
798 |
+
if ( is_object( $value_object ) && property_exists( $value_object, 'source' ) ) {
|
799 |
+
$source = $value_object->source;
|
800 |
+
}
|
801 |
+
}
|
802 |
+
|
803 |
+
return $source;
|
804 |
+
}
|
805 |
+
|
806 |
+
/**
|
807 |
+
* get the value
|
808 |
+
*
|
809 |
+
* @param string $value_string
|
810 |
+
*
|
811 |
+
* @return string
|
812 |
+
*/
|
813 |
+
protected function get_source_string( $value_string ) {
|
814 |
+
$source_string = '';
|
815 |
+
|
816 |
+
if ( ! empty( $value_string ) ) {
|
817 |
+
$value_object = json_decode( $value_string );
|
818 |
+
|
819 |
+
if ( property_exists( $value_object, 'm' ) && property_exists( $value_object->m[0], 's' ) ) {
|
820 |
+
$source_string = json_encode( $value_object->m[0]->s );
|
821 |
+
}
|
822 |
+
}
|
823 |
+
|
824 |
+
return $source_string;
|
825 |
+
}
|
826 |
+
|
827 |
+
/**
|
828 |
+
* makes an xml string of one product including its variations
|
829 |
+
*
|
830 |
+
* @param array $data
|
831 |
+
* @param string $category_name
|
832 |
+
* @param string $description_name
|
833 |
+
*
|
834 |
+
* @return string
|
835 |
+
*/
|
836 |
+
protected function convert_data_to_xml( $data, $category_name, $description_name, $channel ) {
|
837 |
+
return $data ? $this->make_xml_string_row( $data, $category_name, $description_name, $channel ) : '';
|
838 |
+
}
|
839 |
+
|
840 |
+
/**
|
841 |
+
* makes an xml string for one product
|
842 |
+
*
|
843 |
+
* @param array $product Contains all the data from the product.
|
844 |
+
* @param string $category_name Selected category name.
|
845 |
+
* @param string $description_name The name of the description.
|
846 |
+
* @param string $channel Contains the channel id.
|
847 |
+
*
|
848 |
+
* @return string
|
849 |
+
*/
|
850 |
+
protected function make_xml_string_row( $product, $category_name, $description_name, $channel ) {
|
851 |
+
$product_node_name = function_exists( 'product_node_name' ) ? product_node_name( $channel ) : 'item';
|
852 |
+
$node_pre_tag_name = function_exists( 'get_node_pretag' ) ? get_node_pretag( $channel ) : 'g:';
|
853 |
+
$product_node = apply_filters( 'tvc_xml_product_node_name', $product_node_name, $channel );
|
854 |
+
$node_pre_tag = apply_filters( 'tvc_xml_product_pre_tag_name', $node_pre_tag_name, $channel );
|
855 |
+
$tags_with_sub_tags = $this->_channel_class->keys_that_have_sub_tags();
|
856 |
+
$tags_repeated_fields = $this->_channel_class->keys_that_can_be_used_more_than_once();
|
857 |
+
$sub_keys_for_subs = $this->_channel_class->sub_keys_for_sub_tags();
|
858 |
+
|
859 |
+
$this->_channel_class->add_xml_sub_tags( $product, $sub_keys_for_subs, $tags_with_sub_tags, $node_pre_tag );
|
860 |
+
$xml_string = "<$product_node>";
|
861 |
+
|
862 |
+
// for each product value item
|
863 |
+
foreach ( $product as $key => $value ) {
|
864 |
+
if ( ! is_array( $value ) ) {
|
865 |
+
$xml_string .= $this->make_xml_string( $key, $value, $category_name, $description_name, $node_pre_tag, $tags_with_sub_tags, $tags_repeated_fields, $channel );
|
866 |
+
} else {
|
867 |
+
$xml_string .= $this->make_array_string( $key, $value, $node_pre_tag, $channel );
|
868 |
+
}
|
869 |
+
}
|
870 |
+
|
871 |
+
$xml_string .= "</$product_node>";
|
872 |
+
|
873 |
+
return $xml_string;
|
874 |
+
}
|
875 |
+
|
876 |
+
/**
|
877 |
+
* makes an csv string of one product including its variations
|
878 |
+
*
|
879 |
+
* @param array $data
|
880 |
+
* @param array $active_fields
|
881 |
+
* @param string $csv_separator
|
882 |
+
*
|
883 |
+
* @return string
|
884 |
+
*/
|
885 |
+
protected function convert_data_to_csv( $data, $active_fields, $csv_separator ) {
|
886 |
+
if ( $data ) {
|
887 |
+
if ( count( $data ) > count( $active_fields ) ) {
|
888 |
+
$support_class = new TVC_Feed_Support();
|
889 |
+
$support_class->correct_active_fields_list( $active_fields );
|
890 |
+
}
|
891 |
+
|
892 |
+
// the first row in a csv file should contain the index, the following rows the data
|
893 |
+
return $this->make_comma_separated_string_from_data_array( $data, $active_fields, $this->_feed_data->channel, $csv_separator );
|
894 |
+
} else {
|
895 |
+
return '';
|
896 |
+
}
|
897 |
+
}
|
898 |
+
|
899 |
+
/**
|
900 |
+
* makes a tab separated string for a tsv file
|
901 |
+
*
|
902 |
+
* @param array $data
|
903 |
+
*
|
904 |
+
* @return string
|
905 |
+
*/
|
906 |
+
protected function convert_data_to_tsv( $data ) {
|
907 |
+
if ( $data ) {
|
908 |
+
return $this->make_tab_delimited_string_from_data_array( $data );
|
909 |
+
} else {
|
910 |
+
return '';
|
911 |
+
}
|
912 |
+
}
|
913 |
+
|
914 |
+
/**
|
915 |
+
* @param $data
|
916 |
+
* @return string
|
917 |
+
*/
|
918 |
+
protected function convert_data_to_txt( $data ) {
|
919 |
+
if ( $data ) {
|
920 |
+
return $this->make_tab_delimited_string_from_data_array( $data );
|
921 |
+
} else {
|
922 |
+
return '';
|
923 |
+
}
|
924 |
+
}
|
925 |
+
|
926 |
+
/**
|
927 |
+
* takes one row data and converts it to a tab delimited string
|
928 |
+
*
|
929 |
+
* @param array $row_data
|
930 |
+
*
|
931 |
+
* @return string
|
932 |
+
*/
|
933 |
+
protected function make_tab_delimited_string_from_data_array( $row_data ) {
|
934 |
+
$row_string = '';
|
935 |
+
|
936 |
+
foreach ( $row_data as $row_item ) {
|
937 |
+
$a_row_item = ! is_array( $row_item ) ? preg_replace( "/\r|\n/", "", $row_item ) : implode( ', ', $row_item );
|
938 |
+
$clean_row_item = strip_tags( $a_row_item );
|
939 |
+
$row_string .= $clean_row_item . "\t";
|
940 |
+
}
|
941 |
+
|
942 |
+
$row = trim( $row_string ); // removes the tab at the end of the line
|
943 |
+
|
944 |
+
return $row . "\r\n";
|
945 |
+
}
|
946 |
+
|
947 |
+
/**
|
948 |
+
* Takes the data for one row and converts it to a comma separated string that fits into the feed.
|
949 |
+
*
|
950 |
+
* @param array $row_data Array with the attribute name => attribute data.
|
951 |
+
* @param array $active_fields Array containing the attributes that are active and need to go into the feed.
|
952 |
+
* @param string $channel Channel id.
|
953 |
+
* @param string $separator Requested data separator (default ,).
|
954 |
+
*
|
955 |
+
* @return string
|
956 |
+
*/
|
957 |
+
public function make_comma_separated_string_from_data_array( $row_data, $active_fields, $channel, $separator = ',' ) {
|
958 |
+
$row_string = '';
|
959 |
+
|
960 |
+
$quotes_not_allowed = channel_requires_no_quotes_on_empty_attributes( $channel );
|
961 |
+
|
962 |
+
// @since 2.11.0 allows choosing another separator for array data.
|
963 |
+
$separator_for_arrays = apply_filters( 'tvc_separator_for_arrays_in_csv_feed', '|' );
|
964 |
+
|
965 |
+
// Loop through the active attributes.
|
966 |
+
foreach ( $active_fields as $row_item ) {
|
967 |
+
if ( array_key_exists( $row_item, $row_data ) ) {
|
968 |
+
$clean_row_item = ! is_array( $row_data[ $row_item ] ) ? preg_replace( "/\r|\n/", '', $row_data[ $row_item ] ) : implode( $separator_for_arrays, $row_data[ $row_item ] );
|
969 |
+
} else {
|
970 |
+
$clean_row_item = '';
|
971 |
+
}
|
972 |
+
|
973 |
+
$quotes = $quotes_not_allowed && '' === $clean_row_item ? '' : '"';
|
974 |
+
|
975 |
+
$remove_double_quotes_from_string = str_replace( '"', "'", $clean_row_item );
|
976 |
+
$row_string .= $quotes . $remove_double_quotes_from_string . $quotes . $separator;
|
977 |
+
}
|
978 |
+
|
979 |
+
$row = rtrim( $row_string, $separator ); // Removes the comma at the end of the line.
|
980 |
+
|
981 |
+
return $row . "\r\n";
|
982 |
+
}
|
983 |
+
|
984 |
+
/**
|
985 |
+
* makes the header string for a csv file
|
986 |
+
*
|
987 |
+
* @param array $active_fields
|
988 |
+
* @param string $separator
|
989 |
+
*
|
990 |
+
* @return string
|
991 |
+
*/
|
992 |
+
protected function make_csv_header_string( $active_fields, $separator ) {
|
993 |
+
$header = implode( $separator, $active_fields );
|
994 |
+
|
995 |
+
return $header . "\r\n";
|
996 |
+
}
|
997 |
+
|
998 |
+
/**
|
999 |
+
* make an array of product element strings
|
1000 |
+
*
|
1001 |
+
* @param string $key
|
1002 |
+
* @param array $value
|
1003 |
+
* @param string $google_node_pre_tag
|
1004 |
+
* @param string $channel
|
1005 |
+
*
|
1006 |
+
* @return string
|
1007 |
+
*/
|
1008 |
+
protected function make_array_string( $key, $value, $google_node_pre_tag, $channel ) {
|
1009 |
+
$xml_strings = '';
|
1010 |
+
$tags_with_sub_tags = $this->_channel_class->keys_that_have_sub_tags();
|
1011 |
+
$tags_repeated_fields = $this->_channel_class->keys_that_can_be_used_more_than_once();
|
1012 |
+
|
1013 |
+
for ( $i = 0; $i < count( $value ); $i ++ ) {
|
1014 |
+
$xml_key = 'Extra_Afbeeldingen' === $key ? 'Extra_Image_' . ( $i + 1 ) : $key; // required for Beslist.nl
|
1015 |
+
$xml_strings .= $this->make_xml_string( $xml_key, $value[ $i ], '', '', $google_node_pre_tag, $tags_with_sub_tags, $tags_repeated_fields, $channel );
|
1016 |
+
}
|
1017 |
+
|
1018 |
+
return $xml_strings;
|
1019 |
+
}
|
1020 |
+
|
1021 |
+
/**
|
1022 |
+
* Generates an xml node.
|
1023 |
+
*
|
1024 |
+
* Returns an xml node for a product tag and uses the product data to make the node.
|
1025 |
+
*
|
1026 |
+
* @since 1.1.0
|
1027 |
+
* @access public
|
1028 |
+
*
|
1029 |
+
* @param string $key Note id.
|
1030 |
+
* @param string $xml_value Note value.
|
1031 |
+
* @param string $category_name Category name.
|
1032 |
+
* @param string $description_name Description name.
|
1033 |
+
* @param string $google_node_pre_tag Pre node tag.
|
1034 |
+
* @param array $tags_with_sub_tags Array with tags that have a sub tag construction.
|
1035 |
+
* @param array $tags_repeated_fields Array with tags that are allowed to be placed in the feed more than once
|
1036 |
+
* @param string $channel Selected channel id.
|
1037 |
+
*
|
1038 |
+
* @return string Node string in xml format eg. <id>43</id>.
|
1039 |
+
*/
|
1040 |
+
protected function make_xml_string( $key, $xml_value, $category_name, $description_name, $google_node_pre_tag, $tags_with_sub_tags, $tags_repeated_fields, $channel ) {
|
1041 |
+
$xml_string = '';
|
1042 |
+
$repeated_field = ! in_array( $key, $tags_repeated_fields ) ? false : true;
|
1043 |
+
$subtag_sep = apply_filters( 'tvc_sub_tag_separator', '||' );
|
1044 |
+
|
1045 |
+
if ( substr( $xml_value, 0, 5 ) === '!sub:' ) {
|
1046 |
+
$sub_array = explode( "|", $xml_value );
|
1047 |
+
$sa = $sub_array[0];
|
1048 |
+
$st = explode( ":", $sa );
|
1049 |
+
$sub_tag = $st[1];
|
1050 |
+
$xml_value = "<$google_node_pre_tag$sub_tag>$sub_array[1]</$google_node_pre_tag$sub_tag>";
|
1051 |
+
}
|
1052 |
+
|
1053 |
+
if ( $repeated_field && ! is_array( $xml_value ) ) {
|
1054 |
+
$xml_value = explode( $subtag_sep, $xml_value );
|
1055 |
+
}
|
1056 |
+
|
1057 |
+
// keys to be added in a CDATA bracket to the xml feed
|
1058 |
+
$cdata_keys = apply_filters( 'tvc_cdata_keys', array(
|
1059 |
+
$category_name,
|
1060 |
+
$description_name,
|
1061 |
+
'title'
|
1062 |
+
) );
|
1063 |
+
|
1064 |
+
if ( ! is_array( $xml_value ) && ! in_array( $key, $tags_with_sub_tags ) ) {
|
1065 |
+
if ( in_array( $key, $cdata_keys ) ) {
|
1066 |
+
$xml_value = $this->convert_to_character_data_string( $xml_value ); // put in a ![CDATA[...]] bracket
|
1067 |
+
} else {
|
1068 |
+
$xml_value = $this->convert_to_xml_value( $xml_value );
|
1069 |
+
}
|
1070 |
+
}
|
1071 |
+
|
1072 |
+
$google_suffix_exceptions = apply_filters( 'tvc_google_suffux_exceptions', array(
|
1073 |
+
'title',
|
1074 |
+
'link'
|
1075 |
+
) );
|
1076 |
+
|
1077 |
+
// as of October 2016 google removed the need for a g: suffix only for title and link. Facebook still requires it
|
1078 |
+
if ( in_array( $key, $google_suffix_exceptions ) ) {
|
1079 |
+
$google_node_pre_tag = $channel === '1' ? '' : $google_node_pre_tag;
|
1080 |
+
}
|
1081 |
+
|
1082 |
+
if ( $key !== '' ) {
|
1083 |
+
if ( is_array( $xml_value ) && $repeated_field ) {
|
1084 |
+
foreach ( $xml_value as $value_item ) {
|
1085 |
+
$xml_string .= $this->add_xml_string( $key, $value_item, $google_node_pre_tag );
|
1086 |
+
}
|
1087 |
+
} else {
|
1088 |
+
$xml_string = $this->add_xml_string( $key, $xml_value, $google_node_pre_tag );
|
1089 |
+
}
|
1090 |
+
}
|
1091 |
+
|
1092 |
+
return $xml_string;
|
1093 |
+
}
|
1094 |
+
|
1095 |
+
/**
|
1096 |
+
* Generates a single xml line string
|
1097 |
+
*
|
1098 |
+
* @since 1.9.0
|
1099 |
+
*
|
1100 |
+
* @param string $key
|
1101 |
+
* @param string $xml_value
|
1102 |
+
* @param string $google_node_pre_tag
|
1103 |
+
*
|
1104 |
+
* @return string
|
1105 |
+
*/
|
1106 |
+
protected function add_xml_string( $key, $xml_value, $google_node_pre_tag ) {
|
1107 |
+
$not_allowed_characters = array( ' ', '-' );
|
1108 |
+
$clean_key = str_replace( $not_allowed_characters, '_', $key );
|
1109 |
+
|
1110 |
+
return "<$google_node_pre_tag$clean_key>$xml_value</$google_node_pre_tag$clean_key>";
|
1111 |
+
}
|
1112 |
+
|
1113 |
+
/**
|
1114 |
+
* converts an ordinary xml string into a CDATA string
|
1115 |
+
*
|
1116 |
+
* @param string $string
|
1117 |
+
*
|
1118 |
+
* @return string
|
1119 |
+
*/
|
1120 |
+
protected function convert_to_character_data_string( $string ) {
|
1121 |
+
return "<![CDATA[ $string ]]>";
|
1122 |
+
}
|
1123 |
+
|
1124 |
+
/**
|
1125 |
+
* can be overridden by a channel specific function in its class-feed.php
|
1126 |
+
*
|
1127 |
+
* @since 1.9.0
|
1128 |
+
*
|
1129 |
+
* @param $product array Pointer to the product data.
|
1130 |
+
* @param $sub_keys_for_subs array Array with the tags that can be placed in the feed as a sub tag (eg. <loyalty_points><ratio>).
|
1131 |
+
* @param $tags_repeated_fields array Array with tags of fields that can have more than one instance in the feed.
|
1132 |
+
* @param $node_pre_tag string The channel dependant pre tag (eg. g: for Google Feeds).
|
1133 |
+
*
|
1134 |
+
* @return array The product with the correct xml tags.
|
1135 |
+
*/
|
1136 |
+
public function add_xml_sub_tags( &$product, $sub_keys_for_subs, $tags_repeated_fields, $node_pre_tag ) {
|
1137 |
+
$sub_tags = array_intersect_key( $product, array_flip( $sub_keys_for_subs ) );
|
1138 |
+
|
1139 |
+
if ( count( $sub_tags ) < 1 ) {
|
1140 |
+
return $product;
|
1141 |
+
}
|
1142 |
+
|
1143 |
+
$subtag_sep = apply_filters( 'tvc_sub_tag_separator', '||' );
|
1144 |
+
$tags_value = array();
|
1145 |
+
|
1146 |
+
foreach ( $sub_tags as $key => $value ) {
|
1147 |
+
$split = explode( '-', $key );
|
1148 |
+
|
1149 |
+
if ( in_array( $split[0], $tags_repeated_fields ) ) {
|
1150 |
+
$tags_counter = 0;
|
1151 |
+
$value_array = is_array( $value ) ? $value : explode( $subtag_sep, $value );
|
1152 |
+
|
1153 |
+
foreach ( $value_array as $sub_value ) {
|
1154 |
+
$prev_string = array_key_exists( $tags_counter, $tags_value ) ? $tags_value[ $tags_counter ] : '';
|
1155 |
+
$tags_value[ $tags_counter ] = $prev_string . '<' . $node_pre_tag . $split[1] . '>' . $sub_value . '</' . $node_pre_tag . $split[1] . '>';
|
1156 |
+
$tags_counter ++;
|
1157 |
+
}
|
1158 |
+
} else {
|
1159 |
+
$tags_value = array_key_exists( $split[0], $product ) ? $product[ $split[0] ] : '';
|
1160 |
+
$tags_value .= '<' . $node_pre_tag . $split[1] . '>' . $value . '</' . $node_pre_tag . $split[1] . '>';
|
1161 |
+
}
|
1162 |
+
|
1163 |
+
unset( $product[ $key ] );
|
1164 |
+
$product[ $split[0] ] = $tags_value;
|
1165 |
+
}
|
1166 |
+
|
1167 |
+
return $product;
|
1168 |
+
}
|
1169 |
+
|
1170 |
+
/**
|
1171 |
+
* can be overridden by a channel specific function in its class-feed.php
|
1172 |
+
*
|
1173 |
+
* @since 1.9.0
|
1174 |
+
*
|
1175 |
+
* @return array
|
1176 |
+
*/
|
1177 |
+
public function keys_that_have_sub_tags() {
|
1178 |
+
return array();
|
1179 |
+
}
|
1180 |
+
|
1181 |
+
/**
|
1182 |
+
* can be overridden by a channel specific function in its class-feed.php
|
1183 |
+
*
|
1184 |
+
* @since 2.1.0
|
1185 |
+
*
|
1186 |
+
* @return array
|
1187 |
+
*/
|
1188 |
+
public function sub_keys_for_sub_tags() {
|
1189 |
+
return array();
|
1190 |
+
}
|
1191 |
+
|
1192 |
+
/**
|
1193 |
+
* can be overridden by a channel specific function in its class-feed.php
|
1194 |
+
*
|
1195 |
+
* @since 1.9.0
|
1196 |
+
*
|
1197 |
+
* @return array
|
1198 |
+
*/
|
1199 |
+
public function keys_that_can_be_used_more_than_once() {
|
1200 |
+
return array();
|
1201 |
+
}
|
1202 |
+
|
1203 |
+
/**
|
1204 |
+
* replaces certain characters to get a valid xml value
|
1205 |
+
*
|
1206 |
+
* @param string $value_string
|
1207 |
+
*
|
1208 |
+
* @return string
|
1209 |
+
*/
|
1210 |
+
public function convert_to_xml_value( $value_string ) {
|
1211 |
+
$string_without_tags = strip_tags( $value_string );
|
1212 |
+
$prep_string = str_replace(
|
1213 |
+
array(
|
1214 |
+
'&',
|
1215 |
+
'<',
|
1216 |
+
'>',
|
1217 |
+
''',
|
1218 |
+
'"',
|
1219 |
+
' ',
|
1220 |
+
),
|
1221 |
+
array(
|
1222 |
+
'&',
|
1223 |
+
'<',
|
1224 |
+
'>',
|
1225 |
+
'\'',
|
1226 |
+
'"',
|
1227 |
+
'nbsp;',
|
1228 |
+
),
|
1229 |
+
$string_without_tags
|
1230 |
+
);
|
1231 |
+
|
1232 |
+
$clean_xml_string = str_replace(
|
1233 |
+
array(
|
1234 |
+
'&',
|
1235 |
+
'<',
|
1236 |
+
'>',
|
1237 |
+
'\'',
|
1238 |
+
'"',
|
1239 |
+
'nbsp;',
|
1240 |
+
'`',
|
1241 |
+
),
|
1242 |
+
array(
|
1243 |
+
'&',
|
1244 |
+
'<',
|
1245 |
+
'>',
|
1246 |
+
''',
|
1247 |
+
'"',
|
1248 |
+
' ',
|
1249 |
+
'',
|
1250 |
+
),
|
1251 |
+
$prep_string
|
1252 |
+
);
|
1253 |
+
|
1254 |
+
return $clean_xml_string;
|
1255 |
+
}
|
1256 |
+
|
1257 |
+
/**
|
1258 |
+
* get formal woocommerce custom fields data
|
1259 |
+
*
|
1260 |
+
* @param string $id
|
1261 |
+
* @param string $parent_product_id @since 2.0.9
|
1262 |
+
* @param string $field
|
1263 |
+
*
|
1264 |
+
* @return string
|
1265 |
+
*/
|
1266 |
+
protected function get_custom_field_data( $id, $parent_product_id, $field ) {
|
1267 |
+
$custom_string = '';
|
1268 |
+
$taxonomy = 'pa_' . $field;
|
1269 |
+
$custom_values = get_the_terms( $id, $taxonomy );
|
1270 |
+
|
1271 |
+
if ( ! $custom_values && 0 !== $parent_product_id ) {
|
1272 |
+
$custom_values = get_the_terms( $parent_product_id, $taxonomy );
|
1273 |
+
}
|
1274 |
+
|
1275 |
+
if ( $custom_values ) {
|
1276 |
+
foreach ( $custom_values as $custom_value ) {
|
1277 |
+
$custom_string .= $custom_value->name . ', ';
|
1278 |
+
}
|
1279 |
+
}
|
1280 |
+
|
1281 |
+
return $custom_string ? substr( $custom_string, 0, - 2 ) : '';
|
1282 |
+
}
|
1283 |
+
|
1284 |
+
/**
|
1285 |
+
* get third party custom field data
|
1286 |
+
*
|
1287 |
+
* @since 1.6.0
|
1288 |
+
*
|
1289 |
+
* @param string $feed_id
|
1290 |
+
* @param string $parent_product_id @since 2.0.9
|
1291 |
+
* @param string $field
|
1292 |
+
*
|
1293 |
+
* @return string
|
1294 |
+
*/
|
1295 |
+
protected function get_third_party_custom_field_data( $feed_id, $parent_product_id, $field ) {
|
1296 |
+
$result = '';
|
1297 |
+
$product_brand = '';
|
1298 |
+
|
1299 |
+
// YITH Brands plugin
|
1300 |
+
if ( get_option( 'yith_wcbr_brands_label' ) === $field ) { // YITH Brands plugin active
|
1301 |
+
if ( has_term( '', 'yith_product_brand', $feed_id ) ) {
|
1302 |
+
$product_brand = get_the_terms( $feed_id, 'yith_product_brand' );
|
1303 |
+
}
|
1304 |
+
|
1305 |
+
if ( ! $product_brand && 0 !== $parent_product_id && has_term( '', 'yith_product_brand', $parent_product_id ) ) {
|
1306 |
+
$product_brand = get_the_terms( $parent_product_id, 'yith_product_brand' );
|
1307 |
+
}
|
1308 |
+
|
1309 |
+
if ( $product_brand && ! is_wp_error( $product_brand ) ) {
|
1310 |
+
foreach ( $product_brand as $brand ) {
|
1311 |
+
$result .= $brand->name . ', ';
|
1312 |
+
}
|
1313 |
+
}
|
1314 |
+
}
|
1315 |
+
|
1316 |
+
// WooCommerce Brands plugin
|
1317 |
+
if (
|
1318 |
+
in_array(
|
1319 |
+
'woocommerce-brands/woocommerce-brands.php',
|
1320 |
+
apply_filters(
|
1321 |
+
'active_plugins',
|
1322 |
+
get_option( 'active_plugins' )
|
1323 |
+
)
|
1324 |
+
)
|
1325 |
+
) {
|
1326 |
+
|
1327 |
+
if ( has_term( '', 'product_brand', $feed_id ) ) {
|
1328 |
+
$product_brand = get_the_terms( $feed_id, 'product_brand' );
|
1329 |
+
}
|
1330 |
+
|
1331 |
+
if ( ! $product_brand && 0 !== $parent_product_id && has_term( '', 'product_brand', $parent_product_id ) ) {
|
1332 |
+
$product_brand = get_the_terms( $parent_product_id, 'product_brand' );
|
1333 |
+
}
|
1334 |
+
|
1335 |
+
if ( $product_brand && ! is_wp_error( $product_brand ) ) {
|
1336 |
+
foreach ( $product_brand as $brand ) {
|
1337 |
+
$result .= $brand->name . ', ';
|
1338 |
+
}
|
1339 |
+
} elseif ( is_wp_error( $product_brand ) ) {
|
1340 |
+
do_action( 'tvc_feed_generation_warning', $feed_id, $product_brand ); // @since 2.3.0
|
1341 |
+
}
|
1342 |
+
}
|
1343 |
+
|
1344 |
+
return $result ? substr( $result, 0, - 2 ) : '';
|
1345 |
+
}
|
1346 |
+
|
1347 |
+
/**
|
1348 |
+
* adds data to the product that require a procedure to get
|
1349 |
+
*
|
1350 |
+
* @param object $product
|
1351 |
+
* @param array $active_field_names
|
1352 |
+
* @param string $selected_language
|
1353 |
+
* @param string $feed_id
|
1354 |
+
*
|
1355 |
+
* @return bool
|
1356 |
+
*/
|
1357 |
+
protected function add_procedural_data( &$product, $active_field_names, $selected_language, $feed_id ) {
|
1358 |
+
$woocommerce_product = wc_get_product( $product->ID );
|
1359 |
+
|
1360 |
+
if ( false === $woocommerce_product ) {
|
1361 |
+
$msg = sprintf( 'Failed to get the WooCommerce products procedural data from product %s.', $product->ID );
|
1362 |
+
do_action( 'tvc_feed_generation_warning', $feed_id, $msg ); // @since 2.3.0
|
1363 |
+
|
1364 |
+
return false;
|
1365 |
+
}
|
1366 |
+
|
1367 |
+
$woocommerce_parent_id = $woocommerce_product->get_parent_id();
|
1368 |
+
$woocommerce_product_parent = $woocommerce_product && ( $woocommerce_product->is_type( 'variable' ) ||
|
1369 |
+
$woocommerce_product->is_type( 'variation' ) ) ? wc_get_product( $woocommerce_parent_id ) : null;
|
1370 |
+
|
1371 |
+
if ( false === $woocommerce_product_parent || null === $woocommerce_product_parent ) {
|
1372 |
+
// this product has no parent id so it is possible this is the main of a variable product
|
1373 |
+
// So to make sure the general variation data like min_variation_price are available, copy the product
|
1374 |
+
// in the parent product
|
1375 |
+
$woocommerce_product_parent = $woocommerce_product;
|
1376 |
+
}
|
1377 |
+
|
1378 |
+
if ( in_array( 'shipping_class', $active_field_names ) ) {
|
1379 |
+
if ( $woocommerce_product_parent ) {
|
1380 |
+
$product->shipping_class = $woocommerce_product_parent->get_shipping_class();
|
1381 |
+
} elseif ( $woocommerce_product ) {
|
1382 |
+
$product->shipping_class = $woocommerce_product->get_shipping_class();
|
1383 |
+
}
|
1384 |
+
}
|
1385 |
+
|
1386 |
+
if ( in_array( 'permalink', $active_field_names ) ) {
|
1387 |
+
$permalink = get_permalink( $product->ID );
|
1388 |
+
if ( false === $permalink && 0 !== $woocommerce_parent_id ) {
|
1389 |
+
$permalink = get_permalink( $woocommerce_parent_id );
|
1390 |
+
}
|
1391 |
+
|
1392 |
+
// WPML support
|
1393 |
+
$product->permalink = has_filter( 'tvc_get_wpml_permalink' )
|
1394 |
+
? apply_filters( 'tvc_get_wpml_permalink', $permalink, $selected_language ) : $permalink;
|
1395 |
+
}
|
1396 |
+
|
1397 |
+
if ( in_array( 'attachment_url', $active_field_names ) ) {
|
1398 |
+
// WPML support -> Returns an elements ID in the selected language.
|
1399 |
+
$object_id = has_filter( 'wpml_object_id' ) ? apply_filters( 'wpml_object_id', $product->ID, 'attachment', true ) : $product->ID;
|
1400 |
+
$attachment_url = wp_get_attachment_url( get_post_thumbnail_id( $object_id ) );
|
1401 |
+
|
1402 |
+
// If the attachment url is empty and the product has a parent try getting the attachment url of the parent.
|
1403 |
+
if ( false === $attachment_url && 0 !== $woocommerce_parent_id ) {
|
1404 |
+
// WPML support -> Returns an elements ID in the selected language.
|
1405 |
+
$parent_object_id = has_filter( 'wpml_object_id' ) ? apply_filters( 'wpml_object_id', $woocommerce_parent_id, 'attachment', true ) : $woocommerce_parent_id;
|
1406 |
+
$attachment_url = wp_get_attachment_url( get_post_thumbnail_id( $parent_object_id ) );
|
1407 |
+
}
|
1408 |
+
|
1409 |
+
// WPML support -> Filter the permalink and convert it to a language-specific permalink.
|
1410 |
+
$product->attachment_url = has_filter( 'tvc_get_wpml_permalink' )
|
1411 |
+
? apply_filters( 'tvc_get_wpml_permalink', $attachment_url, $selected_language ) : $attachment_url;
|
1412 |
+
}
|
1413 |
+
|
1414 |
+
if ( in_array( 'product_cat', $active_field_names ) ) {
|
1415 |
+
$product->product_cat = TVC_Taxonomies::get_shop_categories( $product->ID );
|
1416 |
+
if ( '' === $product->product_cat && 0 !== $woocommerce_parent_id ) {
|
1417 |
+
$product->product_cat = TVC_Taxonomies::get_shop_categories( $woocommerce_parent_id );
|
1418 |
+
}
|
1419 |
+
}
|
1420 |
+
|
1421 |
+
if ( in_array( 'product_cat_string', $active_field_names ) ) {
|
1422 |
+
$product->product_cat_string = TVC_Taxonomies::make_shop_taxonomies_string( $product->ID );
|
1423 |
+
if ( '' === $product->product_cat_string && 0 !== $woocommerce_parent_id ) {
|
1424 |
+
$product->product_cat_string = TVC_Taxonomies::make_shop_taxonomies_string( $woocommerce_parent_id );
|
1425 |
+
}
|
1426 |
+
}
|
1427 |
+
|
1428 |
+
if ( in_array( 'last_update', $active_field_names ) ) {
|
1429 |
+
$product->last_update = date( 'Y-m-d H:i:s', current_time( 'timestamp' ) );
|
1430 |
+
}
|
1431 |
+
|
1432 |
+
if ( in_array( '_wp_attachement_metadata', $active_field_names ) ) {
|
1433 |
+
$attachment_id = 0 === $woocommerce_parent_id ? $product->ID : $woocommerce_parent_id;
|
1434 |
+
$product->_wp_attachement_metadata = $this->get_product_image_gallery( $attachment_id, $selected_language );
|
1435 |
+
}
|
1436 |
+
|
1437 |
+
if ( in_array( 'product_tags', $active_field_names ) ) {
|
1438 |
+
$product->product_tags = $this->get_product_tags( $product->ID );
|
1439 |
+
}
|
1440 |
+
|
1441 |
+
if ( in_array( 'wc_currency', $active_field_names ) ) {
|
1442 |
+
// WPML support
|
1443 |
+
$product->wc_currency = has_filter( 'tvc_get_wpml_currency' )
|
1444 |
+
? apply_filters( 'tvc_get_wpml_currency', get_woocommerce_currency(), $selected_language ) : get_woocommerce_currency();
|
1445 |
+
}
|
1446 |
+
|
1447 |
+
if ( $woocommerce_product_parent && ( $woocommerce_product_parent->is_type( 'variable' ) || $woocommerce_product_parent->is_type( 'variation' ) ) ) {
|
1448 |
+
if ( in_array( '_min_variation_price', $active_field_names ) ) {
|
1449 |
+
$product->_min_variation_price = $woocommerce_product_parent ? tvc_prep_money_values( $woocommerce_product_parent->get_variation_price(), $selected_language ) : '';
|
1450 |
+
}
|
1451 |
+
|
1452 |
+
if ( in_array( '_max_variation_price', $active_field_names ) ) {
|
1453 |
+
$product->_max_variation_price = $woocommerce_product_parent ? tvc_prep_money_values( $woocommerce_product_parent->get_variation_price( 'max' ), $selected_language ) : '';
|
1454 |
+
}
|
1455 |
+
|
1456 |
+
if ( in_array( '_min_variation_regular_price', $active_field_names ) ) {
|
1457 |
+
$product->_min_variation_regular_price = $woocommerce_product_parent ? tvc_prep_money_values( $woocommerce_product_parent->get_variation_regular_price(), $selected_language ) : '';
|
1458 |
+
}
|
1459 |
+
|
1460 |
+
if ( in_array( '_max_variation_regular_price', $active_field_names ) ) {
|
1461 |
+
$product->_max_variation_regular_price = $woocommerce_product_parent ? tvc_prep_money_values( $woocommerce_product_parent->get_variation_regular_price( 'max' ), $selected_language ) : '';
|
1462 |
+
}
|
1463 |
+
|
1464 |
+
if ( in_array( '_min_variation_sale_price', $active_field_names ) ) {
|
1465 |
+
$product->_min_variation_sale_price = $woocommerce_product_parent ? tvc_prep_money_values( $woocommerce_product_parent->get_variation_sale_price(), $selected_language ) : '';
|
1466 |
+
}
|
1467 |
+
|
1468 |
+
if ( in_array( '_max_variation_sale_price', $active_field_names ) ) {
|
1469 |
+
$product->_max_variation_sale_price = $woocommerce_product_parent ? tvc_prep_money_values( $woocommerce_product_parent->get_variation_sale_price( 'max' ), $selected_language ) : '';
|
1470 |
+
}
|
1471 |
+
|
1472 |
+
if ( in_array( 'item_group_id', $active_field_names ) ) {
|
1473 |
+
$parent_sku = $woocommerce_product_parent ? $woocommerce_product_parent->get_sku() : '';
|
1474 |
+
|
1475 |
+
if ( $parent_sku ) {
|
1476 |
+
$product->item_group_id = $parent_sku; // best practise
|
1477 |
+
} elseif ( $woocommerce_product_parent && $woocommerce_parent_id ) {
|
1478 |
+
$product->item_group_id = 'GID' . $woocommerce_parent_id;
|
1479 |
+
} else {
|
1480 |
+
$product->item_group_id = '';
|
1481 |
+
}
|
1482 |
+
}
|
1483 |
+
} else {
|
1484 |
+
if ( ! $woocommerce_product_parent->is_type( 'simple' ) && ! $woocommerce_product_parent->is_type( 'grouped' )
|
1485 |
+
&& ! $woocommerce_product_parent->is_type( 'virtual' ) && ! $woocommerce_product_parent->is_type( 'downloadable' )
|
1486 |
+
&& ! $woocommerce_product_parent->is_type( 'external' ) ) {
|
1487 |
+
$msg = sprintf(
|
1488 |
+
'Product type of product %s could not be identified. The products shows as type %s',
|
1489 |
+
$product->ID,
|
1490 |
+
function_exists( 'get_product_type' ) ? get_product_type( $product->ID ) : 'unknown'
|
1491 |
+
);
|
1492 |
+
do_action( 'tvc_feed_generation_warning', $feed_id, $msg ); // @since 2.3.0
|
1493 |
+
}
|
1494 |
+
}
|
1495 |
+
|
1496 |
+
// @since 2.1.4
|
1497 |
+
if ( in_array( 'empty', $active_field_names ) ) {
|
1498 |
+
$product->empty = '';
|
1499 |
+
}
|
1500 |
+
|
1501 |
+
// @since 2.2.0
|
1502 |
+
if ( in_array( 'product_type', $active_field_names ) ) {
|
1503 |
+
$product->type = $woocommerce_product ? $woocommerce_product->get_type() : 'unknown';
|
1504 |
+
}
|
1505 |
+
|
1506 |
+
// @since 2.2.0
|
1507 |
+
if ( in_array( 'product_variation_title_without_attributes', $active_field_names ) ) {
|
1508 |
+
$product_title = get_post_field( 'post_title', $product->ID );
|
1509 |
+
|
1510 |
+
if ( false !== strpos( $product_title, ' - ' ) ) { // assuming that the woocommerce_product_variation_title_attributes_separator is ' - '
|
1511 |
+
$title_parts = explode( ' - ', $product_title );
|
1512 |
+
$product_title = $title_parts[0];
|
1513 |
+
}
|
1514 |
+
|
1515 |
+
$product->product_variation_title_without_attributes = $product_title;
|
1516 |
+
}
|
1517 |
+
|
1518 |
+
$woocommerce_product = null;
|
1519 |
+
|
1520 |
+
return true;
|
1521 |
+
}
|
1522 |
+
|
1523 |
+
/**
|
1524 |
+
* get additional images
|
1525 |
+
*
|
1526 |
+
* @param string $post_id
|
1527 |
+
* @param string $selected_language
|
1528 |
+
*
|
1529 |
+
* @return array|string
|
1530 |
+
*/
|
1531 |
+
protected function get_product_image_gallery( $post_id, $selected_language ) {
|
1532 |
+
$image_urls = array();
|
1533 |
+
$images = 1;
|
1534 |
+
$max_nr_images = 10;
|
1535 |
+
|
1536 |
+
$prdct = wc_get_product( $post_id );
|
1537 |
+
$attachment_ids = $prdct->get_gallery_image_ids();
|
1538 |
+
|
1539 |
+
foreach ( $attachment_ids as $attachment_id ) {
|
1540 |
+
$link = wp_get_attachment_url( $attachment_id );
|
1541 |
+
|
1542 |
+
// WPML support
|
1543 |
+
$image_link = has_filter( 'tvc_get_wpml_permalink' )
|
1544 |
+
? apply_filters( 'tvc_get_wpml_permalink', $link, $selected_language ) : $link;
|
1545 |
+
|
1546 |
+
// correct baseurl for https if required
|
1547 |
+
if ( is_ssl() ) {
|
1548 |
+
$url = str_replace( 'http://', 'https://', $image_link );
|
1549 |
+
} else {
|
1550 |
+
$url = $image_link;
|
1551 |
+
}
|
1552 |
+
|
1553 |
+
array_push( $image_urls, $url );
|
1554 |
+
$images ++;
|
1555 |
+
|
1556 |
+
if ( $images > $max_nr_images ) {
|
1557 |
+
break;
|
1558 |
+
}
|
1559 |
+
}
|
1560 |
+
|
1561 |
+
return ! empty( $image_urls ) ? $image_urls : '';
|
1562 |
+
}
|
1563 |
+
|
1564 |
+
protected function get_product_tags( $id ) {
|
1565 |
+
$product_tags_string = '';
|
1566 |
+
$product_tag_values = get_the_terms( $id, 'product_tag' );
|
1567 |
+
$post_tag_values = get_the_tags( $id );
|
1568 |
+
|
1569 |
+
if ( $product_tag_values ) {
|
1570 |
+
foreach ( $product_tag_values as $product_tag ) {
|
1571 |
+
$product_tags_string .= $product_tag->name . ', ';
|
1572 |
+
}
|
1573 |
+
}
|
1574 |
+
|
1575 |
+
if ( $post_tag_values ) {
|
1576 |
+
foreach ( $post_tag_values as $post_tag ) {
|
1577 |
+
$product_tags_string .= $post_tag->name . ', ';
|
1578 |
+
}
|
1579 |
+
}
|
1580 |
+
|
1581 |
+
return $product_tags_string ? substr( $product_tags_string, 0, - 2 ) : '';
|
1582 |
+
}
|
1583 |
+
}
|
includes/application/tvc-feed-processor-functions.php
ADDED
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* @package TVC Product Review Feed Manager/Functions
|
5 |
+
* @version 1.0.0
|
6 |
+
*/
|
7 |
+
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
+
|
12 |
+
trait TVC_Feed_Processor_Functions {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Adds a string to the feed
|
16 |
+
*
|
17 |
+
* @param array $line_data
|
18 |
+
*
|
19 |
+
* @return boolean
|
20 |
+
*/
|
21 |
+
private function add_file_format_line_to_feed( $line_data ) {
|
22 |
+
return false !== file_put_contents( $this->_feed_file_path, $line_data['file_format_line'], FILE_APPEND ) ? true : false;
|
23 |
+
}
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Adds an error message to the feed
|
27 |
+
*
|
28 |
+
* @param array $error_message_data
|
29 |
+
*
|
30 |
+
* @return boolean
|
31 |
+
*/
|
32 |
+
private function add_error_message_to_feed( $error_message_data ) {
|
33 |
+
return false !== file_put_contents( $this->_feed_file_path, $error_message_data['feed_line_message'], FILE_APPEND ) ? true : false;
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* register the update in the database
|
38 |
+
*
|
39 |
+
* @param string $feed_id
|
40 |
+
* @param string $feed_name
|
41 |
+
* @param string $nr_products
|
42 |
+
* @param string $status
|
43 |
+
*/
|
44 |
+
private function register_feed_update( $feed_id, $feed_name, $nr_products, $status = null ) {
|
45 |
+
$data_class = new TVC_Data();
|
46 |
+
|
47 |
+
// register the update and update the feed Last Change time
|
48 |
+
$data_class->update_feed_data( $feed_id, tvc_get_file_url( $feed_name ), $nr_products );
|
49 |
+
|
50 |
+
$actual_status = $status ? $status : $data_class->get_feed_status( $feed_id );
|
51 |
+
|
52 |
+
if ( '4' !== $actual_status && '5' !== $actual_status && '6' !== $actual_status ) { // no errors
|
53 |
+
$data_class->update_feed_status( $feed_id, intval( $status ) ); // put feed on status hold if no errors are reported
|
54 |
+
}
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* @param $product_id
|
59 |
+
* @param $parent_product_id
|
60 |
+
* @param $post_columns_query_string
|
61 |
+
* @return array|mixed|object|void|null
|
62 |
+
*/
|
63 |
+
private function get_products_main_data( $product_id, $parent_product_id, $post_columns_query_string ) {
|
64 |
+
$queries_class = new TVC_Queries();
|
65 |
+
$prep_meta_class = new TVC_Feed_Value_Editors();
|
66 |
+
|
67 |
+
$product_data = $queries_class->read_post_data( $product_id, $post_columns_query_string );
|
68 |
+
|
69 |
+
// WPML support
|
70 |
+
if ( has_filter( 'wpml_translation' ) ) {
|
71 |
+
$product_data = apply_filters( 'wpml_translation', $product_data, $this->_feed_data->language );
|
72 |
+
}
|
73 |
+
|
74 |
+
// parent ids are required to get the main data from product variations
|
75 |
+
$meta_parent_ids = 0 !== $parent_product_id ? array( $parent_product_id ) : $this->get_meta_parent_ids( $product_id );
|
76 |
+
|
77 |
+
array_unshift( $meta_parent_ids, $product_id ); // add the product id to the parent ids
|
78 |
+
|
79 |
+
$meta_data = $queries_class->read_meta_data( $product_id, $parent_product_id, $meta_parent_ids, $this->_pre_data['database_fields']['meta_fields'] );
|
80 |
+
|
81 |
+
foreach ( $meta_data as $meta ) {
|
82 |
+
$meta_value = $prep_meta_class->prep_meta_values( $meta, $this->_feed_data->language );
|
83 |
+
|
84 |
+
if ( property_exists( $product_data, $meta->meta_key ) ) {
|
85 |
+
$meta_key = $meta->meta_key;
|
86 |
+
|
87 |
+
if ( '' === $product_data->$meta_key ) {
|
88 |
+
$product_data = (object) array_merge( (array) $product_data, array( $meta->meta_key => $meta_value ) );
|
89 |
+
}
|
90 |
+
} else {
|
91 |
+
$product_data = (object) array_merge( (array) $product_data, array( $meta->meta_key => $meta_value ) );
|
92 |
+
}
|
93 |
+
}
|
94 |
+
|
95 |
+
foreach ( $this->_pre_data['database_fields']['active_custom_fields'] as $field ) {
|
96 |
+
$product_data->{$field} = $this->get_custom_field_data( $product_data->ID, $parent_product_id, $field );
|
97 |
+
}
|
98 |
+
|
99 |
+
foreach ( $this->_pre_data['database_fields']['third_party_custom_fields'] as $third_party_field ) {
|
100 |
+
$product_data->{$third_party_field} = $this->get_third_party_custom_field_data( $product_data->ID, $parent_product_id, $third_party_field );
|
101 |
+
}
|
102 |
+
|
103 |
+
$this->add_procedural_data( $product_data, $this->_pre_data['column_names'], $this->_feed_data->language, $this->_feed_data->feedId );
|
104 |
+
|
105 |
+
return $product_data;
|
106 |
+
}
|
107 |
+
}
|
includes/application/tvc-support-fields.php
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* @package TVC Product Review Feed Manager/Functions
|
5 |
+
* @version 1.0.0
|
6 |
+
* @since 2.10.0
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
+
exit;
|
11 |
+
}
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Adds custom fields to the products inventory card that can be used in the feeds.
|
15 |
+
*/
|
16 |
+
function tvc_create_gtin_wc_support_field() {
|
17 |
+
|
18 |
+
// Add the Brand field.
|
19 |
+
woocommerce_wp_text_input(
|
20 |
+
array(
|
21 |
+
'id' => 'tvc_product_brand',
|
22 |
+
'label' => 'Product brand',
|
23 |
+
'class' => 'tvc_product_brand',
|
24 |
+
'desc_tip' => true,
|
25 |
+
'description' => esc_html__('Brand name of the product. If the product has no brand name you can use the manufacturer or supplier name.', 'tvc-product-feed-manager' ),
|
26 |
+
)
|
27 |
+
);
|
28 |
+
|
29 |
+
// Add the GTIN field.
|
30 |
+
woocommerce_wp_text_input(
|
31 |
+
array(
|
32 |
+
'id' => 'tvc_product_gtin',
|
33 |
+
'label' => 'Product GTIN',
|
34 |
+
'class' => 'tvc_product_gtin',
|
35 |
+
'desc_tip' => true,
|
36 |
+
'description' => esc_html__('GTIN refers to a products Global Trade Item Number. You can also use a UPC, EAN, JAN, ISBN or ITF-14 number here.', 'tvc-product-feed-manager' ),
|
37 |
+
)
|
38 |
+
);
|
39 |
+
|
40 |
+
// Add the MPN field.
|
41 |
+
woocommerce_wp_text_input(
|
42 |
+
array(
|
43 |
+
'id' => 'tvc_product_mpn',
|
44 |
+
'label' => 'Product MPN',
|
45 |
+
'class' => 'tvc_product_mpn',
|
46 |
+
'desc_tip' => true,
|
47 |
+
'description' => esc_html__('Add your products Manufacturer Part Number (MPN).', 'tvc-product-feed-manager' ),
|
48 |
+
)
|
49 |
+
);
|
50 |
+
}
|
51 |
+
|
52 |
+
add_action( 'woocommerce_product_options_inventory_product_data', 'tvc_create_gtin_wc_support_field' );
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Saves the custom fields data.
|
56 |
+
*
|
57 |
+
* @param mixed $post_id Post ID of the product.
|
58 |
+
*/
|
59 |
+
function tvc_save_custom_fields( $post_id ) {
|
60 |
+
$product = wc_get_product( $post_id );
|
61 |
+
|
62 |
+
// Get the custom fields data.
|
63 |
+
$brand = isset( $_POST['tvc_product_brand'] ) ? $_POST['tvc_product_brand'] : '';
|
64 |
+
$gtin = isset( $_POST['tvc_product_gtin'] ) ? $_POST['tvc_product_gtin'] : '';
|
65 |
+
$mpn = isset( $_POST['tvc_product_mpn'] ) ? $_POST['tvc_product_mpn'] : '';
|
66 |
+
|
67 |
+
// Save the custom fields data.
|
68 |
+
$product->update_meta_data( 'tvc_product_brand', sanitize_text_field( $brand ) );
|
69 |
+
$product->update_meta_data( 'tvc_product_gtin', sanitize_text_field( $gtin ) );
|
70 |
+
$product->update_meta_data( 'tvc_product_mpn', sanitize_text_field( $mpn ) );
|
71 |
+
|
72 |
+
$product->save();
|
73 |
+
}
|
74 |
+
|
75 |
+
add_action( 'woocommerce_process_product_meta', 'tvc_save_custom_fields' );
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Adds custom fields to the products inventory card of the product variations.
|
79 |
+
*
|
80 |
+
* @param array $loop
|
81 |
+
* @param object $variation_data
|
82 |
+
* @param object $variation
|
83 |
+
*/
|
84 |
+
function tvc_create_mpn_wc_variation_support_field( $loop, $variation_data, $variation ) {
|
85 |
+
|
86 |
+
echo '<div class="options_group form-row form-row-full">';
|
87 |
+
|
88 |
+
// Add the MPN text field to the variation cards.
|
89 |
+
woocommerce_wp_text_input(
|
90 |
+
array(
|
91 |
+
'id' => 'tvc_product_mpn[' . $variation->ID . ']',
|
92 |
+
'label' => esc_html__('Product MPN', 'tvc-product-feed-manager'),
|
93 |
+
'desc_tip' => true,
|
94 |
+
'description' => esc_html__('Add your products Manufacturer Part Number (MPN).', 'tvc-product-feed-manager'),
|
95 |
+
'value' => get_post_meta( $variation->ID, 'tvc_product_mpn', true ),
|
96 |
+
)
|
97 |
+
);
|
98 |
+
|
99 |
+
echo '</div>';
|
100 |
+
}
|
101 |
+
|
102 |
+
add_action( 'woocommerce_variation_options', 'tvc_create_mpn_wc_variation_support_field', 10, 3 );
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Saves the custom fields data of the product variations.
|
106 |
+
*
|
107 |
+
* @param int $post_id
|
108 |
+
*/
|
109 |
+
function tvc_save_variation_custom_fields( $post_id ) {
|
110 |
+
|
111 |
+
// Get the variations mpn.
|
112 |
+
$woocommerce_text_field = $_POST['tvc_product_mpn'][ $post_id ];
|
113 |
+
|
114 |
+
// Update.
|
115 |
+
update_post_meta( $post_id, 'tvc_product_mpn', sanitize_text_field( $woocommerce_text_field ) );
|
116 |
+
}
|
117 |
+
|
118 |
+
add_action( 'woocommerce_save_product_variation', 'tvc_save_variation_custom_fields', 10, 2 );
|
includes/class-enhanced-ecommerce-google-analytics.php
CHANGED
File without changes
|
includes/class-tvc-register-scripts.php
ADDED
@@ -0,0 +1,200 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* TVC Register Scripts Class.
|
4 |
+
*
|
5 |
+
* @package TVC Product Feed Manager/Classes
|
6 |
+
*/
|
7 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
8 |
+
exit;
|
9 |
+
}
|
10 |
+
if ( ! class_exists( 'TVC_Register_Scripts' ) ) :
|
11 |
+
/**
|
12 |
+
* Register Scripts Class
|
13 |
+
*/
|
14 |
+
class TVC_Register_Scripts {
|
15 |
+
// @private storage of scripts version
|
16 |
+
private $_version_stamp;
|
17 |
+
// @private register minified scripts
|
18 |
+
private $_js_min;
|
19 |
+
public function __construct() {
|
20 |
+
$premium_version_nr = TVC_EDD_SL_ITEM_NAME === 'Google Product Feed Manager' ? 'fr-' : 'pr-'; // prefix for version stamp depending on premium or free version
|
21 |
+
$action_level = 2; // for future use
|
22 |
+
$this->_version_stamp = defined( 'WP_DEBUG' ) && WP_DEBUG ? time() : $premium_version_nr . '1.0';
|
23 |
+
$this->_js_min = defined( 'WP_DEBUG' ) && WP_DEBUG ? '' : '.min';
|
24 |
+
// add hooks
|
25 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'tvc_register_required_scripts' ) );
|
26 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'tvc_register_required_nonce' ) );
|
27 |
+
// only load the next hooks when on the Settings page
|
28 |
+
if ( tvc_on_plugins_settings_page() ) {
|
29 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'tvc_register_required_options_page_scripts' ) );
|
30 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'tvc_register_required_options_page_nonce' ) );
|
31 |
+
}
|
32 |
+
if ( 1 === $action_level ) {
|
33 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'tvc_register_level_one_scripts' ) );
|
34 |
+
} elseif ( 2 === $action_level ) {
|
35 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'tvc_register_level_two_scripts' ) );
|
36 |
+
}
|
37 |
+
}
|
38 |
+
/**
|
39 |
+
* Registers all required java scripts for the feed manager pages.
|
40 |
+
*/
|
41 |
+
public function tvc_register_required_scripts() {
|
42 |
+
$screen = get_current_screen();
|
43 |
+
|
44 |
+
if($screen->id == 'toplevel_page_aga-envato-api' || $screen->id == 'aga-google-shopping_page_tvc-product-feed-manager' || $screen->id == 'aga-google-shopping_page_tvc-configuration-page'){
|
45 |
+
wp_register_style("tvc_gmc_style-1", ENHANCAD_PLUGIN_URL . '/admin/css/style.css');
|
46 |
+
wp_enqueue_style( "tvc_gmc_style-1");
|
47 |
+
wp_register_style("tvc_gmc_style-2", ENHANCAD_PLUGIN_URL . '/css/style.css');
|
48 |
+
wp_enqueue_style( "tvc_gmc_style-2");
|
49 |
+
wp_register_style("tvc-product-feed-manager-1", ENHANCAD_PLUGIN_URL . '/css/actionable-google-analytics-admin.css');
|
50 |
+
wp_enqueue_style( "tvc-product-feed-manager-1");
|
51 |
+
wp_register_script( 'tvc_gmc_bootstrap-script-1', ENHANCAD_PLUGIN_URL . '/includes/setup/js/bootstrap' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
52 |
+
wp_enqueue_script( 'tvc_gmc_bootstrap-script-1');
|
53 |
+
wp_register_script( 'tvc_gmc_bootstrap-script-1', ENHANCAD_PLUGIN_URL . '/includes/setup/js/jquery-3.5.1.slim' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
54 |
+
wp_enqueue_script( 'tvc_gmc_bootstrap-script-1');
|
55 |
+
wp_register_script( 'tvc_gmc_bootstrap-script-1', ENHANCAD_PLUGIN_URL . '/includes/setup/js/popper' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
56 |
+
wp_enqueue_script( 'tvc_gmc_bootstrap-script-1');
|
57 |
+
wp_register_script( 'tvc_gmc-api-script', ENHANCAD_PLUGIN_URL . '/includes/setup/js/merchant-center.js', array( 'jquery' ), $this->_version_stamp, true );
|
58 |
+
wp_enqueue_script( 'tvc_gmc-api-script');
|
59 |
+
//wp_enqueue_script( 'tvc-product-feed-manager', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/sweetalert' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
60 |
+
wp_register_script( 'tvc-product-feed-manager-fa', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/fontawesome.js', array( 'jquery' ), $this->_version_stamp, false );
|
61 |
+
wp_enqueue_script( 'tvc-product-feed-manager-fa');
|
62 |
+
wp_register_style('aga_bootstrap', '//maxcdn.bootstrapcdn.com/bootstrap/4.5.1/css/bootstrap.min.css');
|
63 |
+
wp_enqueue_style('aga_bootstrap');
|
64 |
+
}
|
65 |
+
// enqueue notice handling script
|
66 |
+
wp_enqueue_script( 'tvc_message-handling-script', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/tvc_msg_events' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
67 |
+
// do not load the other scripts unless a tvc page is on
|
68 |
+
|
69 |
+
wp_register_style( 'tvc-product-feed-manager', ENHANCAD_PLUGIN_URL . '/css/tvc_admin-page' . $this->_js_min . '.css', '', $this->_version_stamp, 'screen' );
|
70 |
+
wp_enqueue_style( 'tvc-product-feed-manager' );
|
71 |
+
// embed the javascript file that makes the Ajax requests
|
72 |
+
wp_register_script( 'tvc_feed-settings-script', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/tvc_feed-form' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp,'screen' );
|
73 |
+
wp_enqueue_script( 'tvc_feed-settings-script');
|
74 |
+
wp_enqueue_script( 'tvc_business-logic-script', ENHANCAD_PLUGIN_URL . '/includes/application/js/tvc_logic.js', array( 'jquery' ), $this->_version_stamp, false );
|
75 |
+
wp_enqueue_script( 'tvc_data-script', ENHANCAD_PLUGIN_URL . '/includes/data/js/tvc_data' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
76 |
+
wp_enqueue_script( 'tvc_event-listener-script1', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/tvc_feed-form-events'. $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
77 |
+
wp_enqueue_script( 'wp_head', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/fontawesome.js', array( 'jquery' ), $this->_version_stamp, false );
|
78 |
+
wp_enqueue_script( 'tvc_form-support-script1', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/tvc_support' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
79 |
+
wp_enqueue_script( 'tvc_verify-inputs-script', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/tvc_verify-inputs' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
80 |
+
wp_enqueue_script( 'tvc_feed-handling-script', ENHANCAD_PLUGIN_URL . '/includes/application/js/tvc_feedhandling' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
81 |
+
wp_enqueue_script( 'tvc_feed-html', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/tvc_feed-html' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
82 |
+
wp_register_script( 'tvc_feed-list-script', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/tvc_feed-list.js', array( 'jquery' ), $this->_version_stamp,'screen' );
|
83 |
+
wp_enqueue_script( 'tvc_feed-list-script');
|
84 |
+
wp_enqueue_script( 'tvc_feed-meta-script', ENHANCAD_PLUGIN_URL . '/includes/application/js/tvc_object-attribute-meta' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
85 |
+
wp_enqueue_script( 'tvc_feed-objects-script', ENHANCAD_PLUGIN_URL . '/includes/application/js/tvc_object-feed' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
86 |
+
wp_enqueue_script( 'tvc_general-functions-script', ENHANCAD_PLUGIN_URL . '/includes/application/js/tvc_general-functions' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
87 |
+
wp_enqueue_script( 'tvc_object-handling-script', ENHANCAD_PLUGIN_URL . '/includes/data/js/tvc_metadatahandling' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false );
|
88 |
+
wp_enqueue_script( 'tvc_script_ajax', ENHANCAD_PLUGIN_URL . '/includes/data/js/tvc_ajaxdatahandling' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, false);
|
89 |
+
wp_enqueue_script( 'tvc_feed-queue-string-script', ENHANCAD_PLUGIN_URL . '/includes/data/js/tvc_feed-queue-string.js', array( 'jquery' ), $this->_version_stamp, false );
|
90 |
+
}
|
91 |
+
/**
|
92 |
+
* Generate the required nonce's.
|
93 |
+
*/
|
94 |
+
public function tvc_register_required_nonce() {
|
95 |
+
// make a unique nonce for all Ajax requests
|
96 |
+
wp_localize_script(
|
97 |
+
'tvc_script_ajax',
|
98 |
+
'myAjaxNonces',
|
99 |
+
array(
|
100 |
+
// URL to wp-admin/admin-ajax.php to process the request
|
101 |
+
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
102 |
+
// generate the nonce's
|
103 |
+
'campaignCategoryListsNonce' => wp_create_nonce( 'tvcajax-campaign-category-lists-nonce' ),
|
104 |
+
'campaignStatusNonce' => wp_create_nonce( 'tvcajax-update-campaign-status-nonce' ),
|
105 |
+
'campaignDeleteNonce' => wp_create_nonce( 'tvcajax-delete-campaign-nonce' ),
|
106 |
+
'categoryListsNonce' => wp_create_nonce( 'tvcajax-category-lists-nonce' ),
|
107 |
+
'deleteFeedNonce' => wp_create_nonce( 'tvcajax-delete-feed-nonce' ),
|
108 |
+
'feedDataNonce' => wp_create_nonce( 'tvcajax-feed-data-nonce' ),
|
109 |
+
'feedStatusNonce' => wp_create_nonce( 'tvcajax-feed-status-nonce' ),
|
110 |
+
'inputFieldsNonce' => wp_create_nonce( 'tvcajax-input-fields-nonce' ),
|
111 |
+
'inputFeedFiltersNonce' => wp_create_nonce( 'tvcajax-feed-filters-nonce' ),
|
112 |
+
'logMessageNonce' => wp_create_nonce( 'tvcajax-log-message-nonce' ),
|
113 |
+
'nextCategoryNonce' => wp_create_nonce( 'tvcajax-next-category-nonce' ),
|
114 |
+
'outputFieldsNonce' => wp_create_nonce( 'tvcajax-output-fields-nonce' ),
|
115 |
+
'postFeedsListNonce' => wp_create_nonce( 'tvcajax-post-feeds-list-nonce' ),
|
116 |
+
'switchFeedStatusNonce' => wp_create_nonce( 'tvcajax-switch-feed-status-nonce' ),
|
117 |
+
'duplicateFeedNonce' => wp_create_nonce( 'tvcajax-duplicate-existing-feed-nonce' ),
|
118 |
+
'updateFeedDataNonce' => wp_create_nonce( 'tvcajax-update-feed-data-nonce' ),
|
119 |
+
'updateAutoFeedFixNonce' => wp_create_nonce( 'tvcajax-set-auto-feed-fix-nonce' ),
|
120 |
+
'updateFeedFileNonce' => wp_create_nonce( 'tvcajax-update-feed-file-nonce' ),
|
121 |
+
'nextFeedInQueueNonce' => wp_create_nonce( 'tvcajax-next-feed-in-queue-nonce' ),
|
122 |
+
'noticeDismissionNonce' => wp_create_nonce( 'tvcajax-duplicate-backup-nonce' ),
|
123 |
+
)
|
124 |
+
);
|
125 |
+
}
|
126 |
+
/**
|
127 |
+
* Registers all required java scripts for the feed manager Settings page.
|
128 |
+
*/
|
129 |
+
public function tvc_register_required_options_page_scripts() {
|
130 |
+
// enqueue notice handling script
|
131 |
+
wp_enqueue_style( 'tvc-product-feed-manager-setting', ENHANCAD_PLUGIN_URL . '/css/tvc_setting-page' . $this->_js_min . '.css', '', $this->_version_stamp, 'screen' );
|
132 |
+
wp_enqueue_script( 'tvc_message-handling-script', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/tvc_msg_events' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, true );
|
133 |
+
wp_enqueue_style('font_awesome','//use.fontawesome.com/releases/v5.0.13/css/all.css');
|
134 |
+
//==wp_enqueue_script( 'tvc_backup-list-script', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/tvc_backup-list'. $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp,'screen' );
|
135 |
+
wp_enqueue_script( 'tvc_data-handling-script', ENHANCAD_PLUGIN_URL . '/includes/data/js/tvc_ajaxdatahandling' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, true );
|
136 |
+
wp_enqueue_script( 'tvc_setting-script', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/tvc_setting-form' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, true );
|
137 |
+
wp_enqueue_script( 'tvc_event-listener-script', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/tvc_feed-form-events' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, true );
|
138 |
+
wp_enqueue_script( 'tvc_form-support-script', ENHANCAD_PLUGIN_URL . '/includes/user-interface/js/tvc_support' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, true );
|
139 |
+
}
|
140 |
+
/**
|
141 |
+
* Generate the nonce's for the Settings page.
|
142 |
+
*/
|
143 |
+
public function tvc_register_required_options_page_nonce() {
|
144 |
+
// make a unique nonce for all Ajax requests
|
145 |
+
wp_localize_script(
|
146 |
+
'tvc_data-handling-script',
|
147 |
+
'myAjaxNonces',
|
148 |
+
array(
|
149 |
+
// URL to wp-admin/admin-ajax.php to process the request
|
150 |
+
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
151 |
+
// generate the required nonce's
|
152 |
+
'setAutoFeedFixNonce' => wp_create_nonce( 'tvcajax-auto-feed-fix-nonce' ),
|
153 |
+
'setBackgroundModeNonce' => wp_create_nonce( 'tvcajax-background-mode-nonce' ),
|
154 |
+
'setFeedLoggerStatusNonce' => wp_create_nonce( 'tvcajax-logger-status-nonce' ),
|
155 |
+
'setShowPINonce' => wp_create_nonce( 'tvcajax-show-pi-nonce' ),
|
156 |
+
'setThirdPartyKeywordsNonce' => wp_create_nonce( 'tvcajax-set-third-party-keywords-nonce' ),
|
157 |
+
'setNoticeMailaddressNonce' => wp_create_nonce( 'tvcajax-set-notice-mailaddress-nonce' ),
|
158 |
+
'setBatchProcessingLimitNonce' => wp_create_nonce( 'tvcajax-set-batch-processing-limit-nonce' ),
|
159 |
+
'backupNonce' => wp_create_nonce( 'tvcajax-backup-nonce' ),
|
160 |
+
'deleteBackupNonce' => wp_create_nonce( 'tvcajax-delete-backup-nonce' ),
|
161 |
+
'restoreBackupNonce' => wp_create_nonce( 'tvcajax-restore-backup-nonce' ),
|
162 |
+
'duplicateBackupNonce' => wp_create_nonce( 'tvcajax-duplicate-backup-nonce' ),
|
163 |
+
'postBackupListNonce' => wp_create_nonce( 'tvcajax-backups-list-nonce' ),
|
164 |
+
'postSetupOptionsNonce' => wp_create_nonce( 'tvcajax-setting-options-nonce' ),
|
165 |
+
'setClearFeedProcessNonce' => wp_create_nonce( 'tvcajax-clear-feed-nonce' ),
|
166 |
+
'setReInitiateNonce' => wp_create_nonce( 'tvcajax-reinitiate-nonce' ),
|
167 |
+
)
|
168 |
+
);
|
169 |
+
}
|
170 |
+
public function tvc_register_level_one_scripts() {
|
171 |
+
if ( ! tvc_on_own_main_plugin_page() ) {
|
172 |
+
return;
|
173 |
+
}
|
174 |
+
$data = new TVC_Data;
|
175 |
+
$installed_channels = $data->get_channels();
|
176 |
+
wp_enqueue_script( 'tvc_channel-functions-script', ENHANCAD_PLUGIN_URL . '/includes/application/js/tvc_channel-functions' . $this->_js_min . '.js', array( 'jquery' ), $this->_version_stamp, true );
|
177 |
+
foreach ( $installed_channels as $channel ) {
|
178 |
+
wp_enqueue_script( 'tvc_' . $channel['short'] . '-source-script', TVC_UPLOADS_URL . '/tvc-channels/' . $channel['short'] . '/tvc_' . $channel['short'] . '-source.js', array( 'jquery' ), $this->_version_stamp, true );
|
179 |
+
}
|
180 |
+
}
|
181 |
+
public function tvc_register_level_two_scripts() {
|
182 |
+
wp_enqueue_script(
|
183 |
+
'tvc_channel-functions-script',
|
184 |
+
ENHANCAD_PLUGIN_URL . '/includes/application/js/tvc_channel-functions.js',
|
185 |
+
array( 'jquery' ),
|
186 |
+
$this->_version_stamp,
|
187 |
+
false
|
188 |
+
);
|
189 |
+
wp_enqueue_script(
|
190 |
+
'tvc_google-source-script',
|
191 |
+
ENHANCAD_PLUGIN_URL . '/includes/application/google/tvc_google-source.js',
|
192 |
+
array( 'jquery' ),
|
193 |
+
$this->_version_stamp,
|
194 |
+
false
|
195 |
+
);
|
196 |
+
}
|
197 |
+
}
|
198 |
+
// End of TVC_Register_Scripts class
|
199 |
+
endif;
|
200 |
+
$my_ajax_registration_class = new TVC_Register_Scripts();
|
includes/data/class-tvc-ajax-calls.php
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Ajax Calls Class.
|
5 |
+
*
|
6 |
+
* @package TVC Product Feed Manager/Data/Classes
|
7 |
+
* @version 1.0.1
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Ajax_Calls' ) ) :
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Feed Controller Class
|
18 |
+
*/
|
19 |
+
class TVC_Ajax_Calls {
|
20 |
+
|
21 |
+
public $_queries;
|
22 |
+
public $_files;
|
23 |
+
|
24 |
+
public function __construct() { }
|
25 |
+
|
26 |
+
protected function safe_ajax_call( $nonce, $registered_nonce_name ) {
|
27 |
+
// check the nonce
|
28 |
+
/*if ( ! wp_verify_nonce( $nonce, $registered_nonce_name ) ) {
|
29 |
+
die( 'You are not allowed to do this!' );
|
30 |
+
}*/
|
31 |
+
|
32 |
+
// only return results when the user is an admin with manage options
|
33 |
+
if ( is_admin() ) {
|
34 |
+
return true;
|
35 |
+
} else {
|
36 |
+
return false;
|
37 |
+
}
|
38 |
+
}
|
39 |
+
}
|
40 |
+
// end of TVC_Ajax_Calls class
|
41 |
+
endif;
|
includes/data/class-tvc-ajax-data.php
ADDED
@@ -0,0 +1,448 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Ajax Data Class.
|
5 |
+
*
|
6 |
+
* @package TVC Product Feed Manager/Data/Classes
|
7 |
+
* @version 1.10.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Ajax_Data' ) ) :
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Ajax Data Class
|
18 |
+
*/
|
19 |
+
class TVC_Ajax_Data extends TVC_Ajax_Calls {
|
20 |
+
|
21 |
+
public function __construct() {
|
22 |
+
parent::__construct();
|
23 |
+
|
24 |
+
$this->_queries = new TVC_Queries();
|
25 |
+
$this->_files = new TVC_File();
|
26 |
+
|
27 |
+
// hooks
|
28 |
+
add_action( 'wp_ajax_tvcajax-get-list-of-feeds', array( $this, 'tvcajax_get_list_of_feeds' ) );
|
29 |
+
add_action( 'wp_ajax_tvcajax-get-list-of-backups', array( $this, 'tvcajax_get_list_of_backups' ) );
|
30 |
+
add_action( 'wp_ajax_tvcajax-get-settings-options', array( $this, 'tvcajax_get_settings_options' ) );
|
31 |
+
add_action( 'wp_ajax_tvcajax-get-output-fields', array( $this, 'tvcajax_get_output_fields' ) );
|
32 |
+
add_action( 'wp_ajax_tvcajax-get-input-fields', array( $this, 'tvcajax_get_input_fields' ) );
|
33 |
+
add_action( 'wp_ajax_tvcajax-get-feed-data', array( $this, 'tvcajax_get_feed_data' ) );
|
34 |
+
add_action( 'wp_ajax_tvcajax-get-feed-status', array( $this, 'tvcajax_get_feed_status' ) );
|
35 |
+
add_action( 'wp_ajax_tvcajax-get-main-feed-filters', array( $this, 'tvcajax_get_feed_filters' ) );
|
36 |
+
add_action( 'wp_ajax_tvcajax-switch-feed-status', array( $this, 'tvcajax_switch_feed_status_between_hold_and_ok' ) );
|
37 |
+
add_action( 'wp_ajax_tvcajax-duplicate-existing-feed', array( $this, 'tvcajax_duplicate_feed_data' ) );
|
38 |
+
add_action( 'wp_ajax_tvcajax-update-feed-data', array( $this, 'tvcajax_update_feed_data' ) );
|
39 |
+
add_action( 'wp_ajax_tvcajax-delete-feed', array( $this, 'tvcajax_delete_feed' ) );
|
40 |
+
add_action( 'wp_ajax_tvcajax-backup-current-data', array( $this, 'tvcajax_backup_current_data' ) );
|
41 |
+
add_action( 'wp_ajax_tvcajax-delete-backup-file', array( $this, 'tvcajax_delete_backup_file' ) );
|
42 |
+
add_action( 'wp_ajax_tvcajax-restore-backup-file', array( $this, 'tvcajax_restore_backup_file' ) );
|
43 |
+
add_action( 'wp_ajax_tvcajax-duplicate-backup-file', array( $this, 'tvcajax_duplicate_backup_file' ) );
|
44 |
+
add_action( 'wp_ajax_tvcajax-get-next-feed-in-queue', array( $this, 'tvcajax_get_next_feed_in_queue' ) );
|
45 |
+
add_action( 'wp_ajax_tvcajax-register-notice-dismission', array( $this, 'tvcajax_register_notice_dismission' ) );
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Returns a list of all active feeds to an ajax caller
|
50 |
+
*/
|
51 |
+
public function tvcajax_get_list_of_feeds() {
|
52 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'postFeedsListNonce' ), 'tvcajax-post-feeds-list-nonce' ) ) {
|
53 |
+
$list = $this->_queries->get_feeds_list();
|
54 |
+
|
55 |
+
// the status string entries from the database to identification strings (i.e. OK to ok and On hold in on_hold)
|
56 |
+
if ( $list && ! ctype_lower( $list[0]->status ) ) {
|
57 |
+
tvc_correct_old_feeds_list_status( $list );
|
58 |
+
}
|
59 |
+
|
60 |
+
$this->convert_type_numbers_to_text( $list );
|
61 |
+
|
62 |
+
// add information about the tvc_special_feeds_add_on_active filter to the feed list
|
63 |
+
$result = array(
|
64 |
+
'list' => $list,
|
65 |
+
'special_feed_add_ons_active' => apply_filters( 'tvc_special_feeds_add_on_active', false ),
|
66 |
+
);
|
67 |
+
|
68 |
+
echo json_encode( $result );
|
69 |
+
}
|
70 |
+
|
71 |
+
// IMPORTANT: don't forget to exit
|
72 |
+
exit;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Returns a list of backups the user has made
|
77 |
+
*/
|
78 |
+
public function tvcajax_get_list_of_backups() {
|
79 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'postBackupListNonce' ), 'tvcajax-backups-list-nonce' ) ) {
|
80 |
+
echo json_encode( $this->_files->make_list_of_active_backups() );
|
81 |
+
}
|
82 |
+
|
83 |
+
// IMPORTANT: don't forget to exit
|
84 |
+
exit;
|
85 |
+
}
|
86 |
+
|
87 |
+
public function tvcajax_get_settings_options() {
|
88 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'postSetupOptionsNonce' ), 'tvcajax-setting-options-nonce' ) ) {
|
89 |
+
$options = [
|
90 |
+
get_option( 'tvc_auto_feed_fix' ),
|
91 |
+
get_option( 'tvc_third_party_attribute_keywords' ),
|
92 |
+
get_option( 'tvc_notice_mailaddress' ),
|
93 |
+
get_option( 'tvc_disabled_background_mode' ),
|
94 |
+
];
|
95 |
+
echo json_encode( $options );
|
96 |
+
}
|
97 |
+
|
98 |
+
// IMPORTANT: don't forget to exit
|
99 |
+
exit;
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Retrieves the output fields that are specific for a given merchant and
|
104 |
+
* also adds stored meta data to the output fields
|
105 |
+
*
|
106 |
+
* @access public (ajax triggered)
|
107 |
+
*/
|
108 |
+
public function tvcajax_get_output_fields() {
|
109 |
+
|
110 |
+
// check: if the call is safe
|
111 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'outputFieldsNonce' ), 'tvcajax-output-fields-nonce' ) ) {
|
112 |
+
$data_class = new TVC_Data();
|
113 |
+
|
114 |
+
// get the posted inputs
|
115 |
+
$channel_id = filter_input( INPUT_POST, 'channelId' );
|
116 |
+
$feed_id = filter_input( INPUT_POST, 'feedId' );
|
117 |
+
$channel = trim( $this->_queries->get_channel_short_name_from_db( $channel_id ) );
|
118 |
+
$is_custom = function_exists( 'tvc_channel_is_custom_channel' ) ? tvc_channel_is_custom_channel( $channel_id ) : false;
|
119 |
+
|
120 |
+
if ( ! $is_custom ) {
|
121 |
+
// read the output fields
|
122 |
+
$outputs = $this->_files->get_output_fields_for_specific_channel( $channel );
|
123 |
+
|
124 |
+
// if the feed is a stored feed, look for meta data to add (a feed an id of -1 is a new feed that not yet has been saved)
|
125 |
+
if ( $feed_id >= 0 ) {
|
126 |
+
// add meta data to the feeds output fields
|
127 |
+
$outputs = $data_class->fill_output_fields_with_metadata( $feed_id, $outputs );
|
128 |
+
}
|
129 |
+
} else {
|
130 |
+
$data_class = new TVC_Data();
|
131 |
+
$outputs = $data_class->get_custom_fields_with_metadata( $feed_id );
|
132 |
+
}
|
133 |
+
|
134 |
+
echo json_encode( $outputs );
|
135 |
+
}
|
136 |
+
|
137 |
+
// IMPORTANT: don't forget to exit
|
138 |
+
exit;
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Gets all the different source fields from the custom products and third party sources and combines them into one list
|
143 |
+
*
|
144 |
+
* @access public (ajax triggered)
|
145 |
+
*/
|
146 |
+
public function tvcajax_get_input_fields() {
|
147 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'inputFieldsNonce' ), 'tvcajax-input-fields-nonce' ) ) {
|
148 |
+
$source_id = filter_input( INPUT_POST, 'sourceId' );
|
149 |
+
|
150 |
+
switch ( $source_id ) {
|
151 |
+
case '1':
|
152 |
+
$data_class = new TVC_Data();
|
153 |
+
|
154 |
+
$custom_product_attributes = $this->_queries->get_custom_product_attributes();
|
155 |
+
$custom_product_fields = $this->_queries->get_custom_product_fields();
|
156 |
+
$product_attributes = $this->_queries->get_all_product_attributes();
|
157 |
+
$product_taxonomies = get_taxonomies();
|
158 |
+
$third_party_custom_fields = $data_class->get_third_party_custom_fields();
|
159 |
+
|
160 |
+
$all_source_fields = $this->combine_custom_attributes_and_feeds(
|
161 |
+
$custom_product_attributes,
|
162 |
+
$custom_product_fields,
|
163 |
+
$product_attributes,
|
164 |
+
$product_taxonomies,
|
165 |
+
$third_party_custom_fields
|
166 |
+
);
|
167 |
+
|
168 |
+
echo json_encode( apply_filters( 'tvc_all_source_fields', $all_source_fields ) );
|
169 |
+
break;
|
170 |
+
|
171 |
+
default:
|
172 |
+
if ( 'valid' === get_option( 'tvc_lic_status' ) ) { // error message for paid versions
|
173 |
+
echo '<div id="error">' . esc_html__(
|
174 |
+
'Could not add custom fields because I could not identify the channel.
|
175 |
+
If not already done add the correct channel in the Manage Channels page.
|
176 |
+
Also try to deactivate and then activate the plugin.',
|
177 |
+
'tvc-product-feed-manager'
|
178 |
+
) . '</div>';
|
179 |
+
|
180 |
+
tvc_write_log_file( sprintf( 'Could not define the channel in a valid Premium plugin version. Feed id = %s', $source_id ) );
|
181 |
+
} else { // error message for free version
|
182 |
+
echo '<div id="error">' . esc_html__(
|
183 |
+
'Could not identify the channel.
|
184 |
+
Try to deactivate and then activate the plugin.
|
185 |
+
If that does not work remove the plugin through the WordPress Plugins page and than reinstall and activate it again.',
|
186 |
+
'tvc-product-feed-manager'
|
187 |
+
) . '</div>';
|
188 |
+
|
189 |
+
tvc_write_log_file( sprintf( 'Could not define the channel in a free plugin version. Feed id = %s', $source_id ) );
|
190 |
+
}
|
191 |
+
|
192 |
+
break;
|
193 |
+
}
|
194 |
+
}
|
195 |
+
|
196 |
+
// IMPORTANT: don't forget to exit
|
197 |
+
exit;
|
198 |
+
}
|
199 |
+
|
200 |
+
public function tvcajax_get_feed_filters() {
|
201 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'inputFeedFiltersNonce' ), 'tvcajax-feed-filters-nonce' ) ) {
|
202 |
+
$feed_id = filter_input( INPUT_POST, 'feedId' );
|
203 |
+
|
204 |
+
$data_class = new TVC_Data();
|
205 |
+
$filters = $data_class->get_filter_query( $feed_id );
|
206 |
+
|
207 |
+
echo $filters ? json_encode( $filters ) : '0';
|
208 |
+
}
|
209 |
+
|
210 |
+
// IMPORTANT: don't forget to exit
|
211 |
+
exit;
|
212 |
+
}
|
213 |
+
|
214 |
+
public function tvcajax_get_feed_data() {
|
215 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'feedDataNonce' ), 'tvcajax-feed-data-nonce' ) ) {
|
216 |
+
$feed_id = filter_input( INPUT_POST, 'sourceId' );
|
217 |
+
$feed_data = $this->_queries->read_feed( $feed_id );
|
218 |
+
|
219 |
+
echo json_encode( $feed_data );
|
220 |
+
}
|
221 |
+
|
222 |
+
// IMPORTANT: don't forget to exit
|
223 |
+
exit;
|
224 |
+
}
|
225 |
+
|
226 |
+
public function tvcajax_get_feed_status() {
|
227 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'feedStatusNonce' ), 'tvcajax-feed-status-nonce' ) ) {
|
228 |
+
$feed_id = filter_input( INPUT_POST, 'sourceId' );
|
229 |
+
|
230 |
+
$feed_master = new TVC_Feed_Master_Class( $feed_id );
|
231 |
+
$feed_data = $feed_master->feed_status_check( $feed_id );
|
232 |
+
|
233 |
+
echo json_encode( $feed_data );
|
234 |
+
}
|
235 |
+
|
236 |
+
// IMPORTANT: don't forget to exit
|
237 |
+
exit;
|
238 |
+
}
|
239 |
+
|
240 |
+
public function tvcajax_update_feed_data() {
|
241 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'updateFeedDataNonce' ), 'tvcajax-update-feed-data-nonce' ) ) {
|
242 |
+
// get the posted feed data
|
243 |
+
$ajax_feed_data = json_decode( filter_input( INPUT_POST, 'feed' ) );
|
244 |
+
$feed_filter = filter_input( INPUT_POST, 'feedFilter' );
|
245 |
+
$m_data = filter_input( INPUT_POST, 'metaData' );
|
246 |
+
|
247 |
+
echo TVC_Feed_CRUD_Handler::create_or_update_feed_data( $ajax_feed_data, $m_data, $feed_filter );
|
248 |
+
}
|
249 |
+
|
250 |
+
exit;
|
251 |
+
}
|
252 |
+
|
253 |
+
public function tvcajax_switch_feed_status_between_hold_and_ok() {
|
254 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'switchFeedStatusNonce' ), 'tvcajax-switch-feed-status-nonce' ) ) {
|
255 |
+
$feed_id = filter_input( INPUT_POST, 'feedId' );
|
256 |
+
|
257 |
+
$feed_status = $this->_queries->get_current_feed_status( $feed_id );
|
258 |
+
$current_status = $feed_status[0]->status_id;
|
259 |
+
|
260 |
+
$new_status = '1' === $current_status ? '2' : '1'; // only allow status 1 or 2
|
261 |
+
|
262 |
+
$result = $this->_queries->switch_feed_status( $feed_id, $new_status );
|
263 |
+
|
264 |
+
echo ( false === $result ) ? $current_status : $new_status;
|
265 |
+
}
|
266 |
+
|
267 |
+
// IMPORTANT: don't forget to exit
|
268 |
+
exit;
|
269 |
+
}
|
270 |
+
|
271 |
+
public function tvcajax_duplicate_feed_data() {
|
272 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'duplicateFeedNonce' ), 'tvcajax-duplicate-existing-feed-nonce' ) ) {
|
273 |
+
$feed_id = filter_input( INPUT_POST, 'feedId' );
|
274 |
+
|
275 |
+
echo TVC_Db_Management::duplicate_feed( $feed_id );
|
276 |
+
}
|
277 |
+
|
278 |
+
// IMPORTANT: don't forget to exit
|
279 |
+
exit;
|
280 |
+
}
|
281 |
+
|
282 |
+
public function tvcajax_delete_feed() {
|
283 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'deleteFeedNonce' ), 'tvcajax-delete-feed-nonce' ) ) {
|
284 |
+
$feed_id = filter_input( INPUT_POST, 'feedId' );
|
285 |
+
|
286 |
+
// only return results when the user is an admin with manage options
|
287 |
+
if ( is_admin() ) {
|
288 |
+
TVC_Feed_Controller::remove_id_from_feed_queue( $feed_id );
|
289 |
+
$this->_queries->delete_meta( $feed_id );
|
290 |
+
echo $this->_queries->delete_feed( $feed_id );
|
291 |
+
}
|
292 |
+
}
|
293 |
+
|
294 |
+
// IMPORTANT: don't forget to exit
|
295 |
+
exit;
|
296 |
+
}
|
297 |
+
|
298 |
+
public function tvcajax_backup_current_data() {
|
299 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'backupNonce' ), 'tvcajax-backup-nonce' ) ) {
|
300 |
+
// only take action when the user is an admin with manage options
|
301 |
+
if ( is_admin() ) {
|
302 |
+
$backup_file_name = filter_input( INPUT_POST, 'fileName' );
|
303 |
+
echo TVC_Db_Management::backup_database_tables( $backup_file_name );
|
304 |
+
}
|
305 |
+
}
|
306 |
+
|
307 |
+
// IMPORTANT: don't forget to exit
|
308 |
+
exit;
|
309 |
+
}
|
310 |
+
|
311 |
+
public function tvcajax_delete_backup_file() {
|
312 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'deleteBackupNonce' ), 'tvcajax-delete-backup-nonce' ) ) {
|
313 |
+
// only take action when the user is an admin with manage options
|
314 |
+
if ( is_admin() ) {
|
315 |
+
$backup_file_name = filter_input( INPUT_POST, 'fileName' );
|
316 |
+
TVC_Db_Management::delete_backup_file( $backup_file_name );
|
317 |
+
}
|
318 |
+
}
|
319 |
+
|
320 |
+
// IMPORTANT: don't forget to exit
|
321 |
+
exit;
|
322 |
+
}
|
323 |
+
|
324 |
+
public function tvcajax_restore_backup_file() {
|
325 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'restoreBackupNonce' ), 'tvcajax-restore-backup-nonce' ) ) {
|
326 |
+
// only take action when the user is an admin with manage options
|
327 |
+
if ( is_admin() ) {
|
328 |
+
$backup_file_name = filter_input( INPUT_POST, 'fileName' );
|
329 |
+
echo TVC_Db_Management::restore_backup( $backup_file_name );
|
330 |
+
}
|
331 |
+
}
|
332 |
+
|
333 |
+
// IMPORTANT: don't forget to exit
|
334 |
+
exit;
|
335 |
+
}
|
336 |
+
|
337 |
+
public function tvcajax_duplicate_backup_file() {
|
338 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'duplicateBackupNonce' ), 'tvcajax-duplicate-backup-nonce' ) ) {
|
339 |
+
// only take action when the user is an admin with manage options
|
340 |
+
if ( is_admin() ) {
|
341 |
+
$backup_file_name = filter_input( INPUT_POST, 'fileName' );
|
342 |
+
TVC_Db_Management::duplicate_backup_file( $backup_file_name );
|
343 |
+
}
|
344 |
+
}
|
345 |
+
|
346 |
+
// IMPORTANT: don't forget to exit
|
347 |
+
exit;
|
348 |
+
}
|
349 |
+
|
350 |
+
public function tvcajax_get_next_feed_in_queue() {
|
351 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'nextFeedInQueueNonce' ), 'tvcajax-next-feed-in-queue-nonce' ) ) {
|
352 |
+
$next_feed_id = TVC_Feed_Controller::get_next_id_from_feed_queue();
|
353 |
+
echo false !== $next_feed_id ? $next_feed_id : 'false';
|
354 |
+
}
|
355 |
+
|
356 |
+
// IMPORTANT: don't forget to exit
|
357 |
+
exit;
|
358 |
+
}
|
359 |
+
|
360 |
+
public function tvcajax_register_notice_dismission() {
|
361 |
+
if ( $this->safe_ajax_call( filter_input( INPUT_POST, 'noticeDismissionNonce' ), 'tvcajax-duplicate-backup-nonce' ) ) {
|
362 |
+
|
363 |
+
// only take action when the user is an admin with manage options
|
364 |
+
if ( is_admin() ) {
|
365 |
+
update_option( 'tvc_license_notice_suppressed', true );
|
366 |
+
echo 'true';
|
367 |
+
} else {
|
368 |
+
echo 'false';
|
369 |
+
}
|
370 |
+
}
|
371 |
+
|
372 |
+
// IMPORTANT: don't forget to exit
|
373 |
+
exit;
|
374 |
+
}
|
375 |
+
|
376 |
+
private function combine_custom_attributes_and_feeds( $attributes, $feeds, $product_attributes, $product_taxonomies, $third_party_fields ) {
|
377 |
+
$prev_dup_array = array(); // used to prevent doubles
|
378 |
+
|
379 |
+
foreach ( $feeds as $feed ) {
|
380 |
+
$obj = new stdClass();
|
381 |
+
|
382 |
+
$obj->attribute_name = $feed;
|
383 |
+
$obj->attribute_label = $feed;
|
384 |
+
|
385 |
+
array_push( $attributes, $obj );
|
386 |
+
array_push( $prev_dup_array, $obj->attribute_label );
|
387 |
+
}
|
388 |
+
|
389 |
+
foreach ( $product_taxonomies as $taxonomy ) {
|
390 |
+
if ( ! in_array( $taxonomy, $prev_dup_array ) ) {
|
391 |
+
$obj = new stdClass();
|
392 |
+
$obj->attribute_name = $taxonomy;
|
393 |
+
$obj->attribute_label = $taxonomy;
|
394 |
+
|
395 |
+
array_push( $attributes, $obj );
|
396 |
+
array_push( $prev_dup_array, $taxonomy );
|
397 |
+
}
|
398 |
+
}
|
399 |
+
|
400 |
+
foreach ( $product_attributes as $attribute_string ) {
|
401 |
+
$attribute_object = maybe_unserialize( $attribute_string->meta_value );
|
402 |
+
|
403 |
+
if ( $attribute_object && ( is_object( $attribute_object ) || is_array( $attribute_object ) ) ) {
|
404 |
+
foreach ( $attribute_object as $attribute ) {
|
405 |
+
if ( ! in_array( $attribute['name'], $prev_dup_array ) ) {
|
406 |
+
$obj = new stdClass();
|
407 |
+
$obj->attribute_name = $attribute['name'];
|
408 |
+
$obj->attribute_label = $attribute['name'];
|
409 |
+
|
410 |
+
array_push( $attributes, $obj );
|
411 |
+
array_push( $prev_dup_array, $attribute['name'] );
|
412 |
+
}
|
413 |
+
}
|
414 |
+
} else {
|
415 |
+
if ( $attribute_object ) {
|
416 |
+
tvc_write_log_file( $attribute_object, 'debug' );
|
417 |
+
}
|
418 |
+
}
|
419 |
+
}
|
420 |
+
|
421 |
+
foreach ( $third_party_fields as $field_label ) {
|
422 |
+
if ( ! in_array( $field_label, $prev_dup_array ) ) {
|
423 |
+
$obj = new stdClass();
|
424 |
+
$obj->attribute_name = $field_label;
|
425 |
+
$obj->attribute_label = $field_label;
|
426 |
+
|
427 |
+
array_push( $attributes, $obj );
|
428 |
+
array_push( $prev_dup_array, $field_label );
|
429 |
+
}
|
430 |
+
}
|
431 |
+
|
432 |
+
return $attributes;
|
433 |
+
}
|
434 |
+
|
435 |
+
private function convert_type_numbers_to_text( &$list ) {
|
436 |
+
$feed_types = tvc_list_feed_type_text();
|
437 |
+
|
438 |
+
foreach ( $list as $feed ) {
|
439 |
+
$feed->feed_type_name = $feed_types[ $feed->feed_type_id ];
|
440 |
+
}
|
441 |
+
}
|
442 |
+
}
|
443 |
+
|
444 |
+
// end of TVC_Ajax_Data_Class
|
445 |
+
|
446 |
+
endif;
|
447 |
+
|
448 |
+
$my_ajax_data_class = new TVC_Ajax_Data();
|
includes/data/class-tvc-ajax-file.php
ADDED
@@ -0,0 +1,1081 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Ajax File Class.
|
5 |
+
*
|
6 |
+
* @package TVC Product Feed Manager/Data/Classes
|
7 |
+
*/
|
8 |
+
if(!defined('ABSPATH')){
|
9 |
+
exit;
|
10 |
+
}
|
11 |
+
|
12 |
+
if(!class_exists('TVC_Ajax_File')) :
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Ajax File Class
|
16 |
+
*/
|
17 |
+
class TVC_Ajax_File extends TVC_Ajax_Calls {
|
18 |
+
|
19 |
+
public function __construct(){
|
20 |
+
parent::__construct();
|
21 |
+
|
22 |
+
// hooks
|
23 |
+
add_action('wp_ajax_tvcajax-get-campaign-categories', array($this, 'tvcajax_get_campaign_categories'));
|
24 |
+
add_action('wp_ajax_tvcajax-update-campaign-status', array($this, 'tvcajax_update_campaign_status'));
|
25 |
+
add_action('wp_ajax_tvcajax-delete-campaign', array($this, 'tvcajax_delete_campaign'));
|
26 |
+
add_action('wp_ajax_tvcajax-get-next-categories', array($this, 'tvcajax_read_next_categories'));
|
27 |
+
add_action('wp_ajax_tvcajax-get-category-lists', array($this, 'tvcajax_read_category_lists'));
|
28 |
+
add_action('wp_ajax_tvcajax-delete-feed-file', array($this, 'tvcajax_delete_feed_file'));
|
29 |
+
add_action('wp_ajax_tvcajax-update-feed-file', array($this, 'tvcajax_update_feed_file'));
|
30 |
+
add_action('wp_ajax_tvcajax-log-message', array($this, 'tvcajax_log_message'));
|
31 |
+
add_action('wp_ajax_tvcajax-auto-feed-fix-mode-selection', array($this, 'tvcajax_auto_feed_fix_mode_selection'));
|
32 |
+
add_action('wp_ajax_tvcajax-background-processing-mode-selection', array($this, 'tvcajax_background_processing_mode_selection'));
|
33 |
+
add_action('wp_ajax_tvcajax-feed-logger-status-selection', array($this, 'tvcajax_feed_logger_status_selection'));
|
34 |
+
add_action('wp_ajax_tvcajax-show-product-identifiers-selection', array($this, 'tvcajax_show_product_identifiers_selection'));
|
35 |
+
add_action('wp_ajax_tvcajax-debug-mode-selection', array($this, 'tvcajax_debut_mode_selection'));
|
36 |
+
add_action('wp_ajax_tvcajax-third-party-attribute-keywords', array($this, 'tvcajax_set_third_party_attribute_keywords'));
|
37 |
+
add_action('wp_ajax_tvcajax-set-notice-mailaddress', array($this, 'tvcajax_set_notice_mailaddress'));
|
38 |
+
add_action('wp_ajax_tvcajax-clear-feed-process-data', array($this, 'tvcajax_clear_feed_process_data'));
|
39 |
+
add_action('wp_ajax_tvcajax-reinitiate-plugin', array($this, 'tvcajax_reinitiate_plugin'));
|
40 |
+
add_action('wp_ajax_tvcajax-product-syncup', array($this, 'tvcajax_product_syncup'));
|
41 |
+
add_action('wp_ajax_tvcajax-gmc-category-lists', array($this, 'tvcajax_get_gmc_categories'));
|
42 |
+
add_action('wp_ajax_tvcajax-custom-metrics-dimension', array($this, 'tvcajax_custom_metrics_dimension'));
|
43 |
+
add_action('wp_ajax_tvcajax-store-time-taken', array($this, 'tvcajax_store_time_taken'));
|
44 |
+
}
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Delete the campaign
|
48 |
+
*/
|
49 |
+
public function tvcajax_delete_campaign(){
|
50 |
+
// make sure this call is legal
|
51 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'campaignDeleteNonce'), 'tvcajax-delete-campaign-nonce')){
|
52 |
+
|
53 |
+
$merchantId = filter_input(INPUT_POST, 'merchantId');
|
54 |
+
$customerId = filter_input(INPUT_POST, 'customerId');
|
55 |
+
$campaignId = filter_input(INPUT_POST, 'campaignId');
|
56 |
+
|
57 |
+
$url = 'https://connect.tatvic.com/laravelapi/public/api/campaigns/delete';
|
58 |
+
|
59 |
+
$data = [
|
60 |
+
'merchant_id' => $merchantId,
|
61 |
+
'customer_id' => $customerId,
|
62 |
+
'campaign_id' => $campaignId
|
63 |
+
];
|
64 |
+
|
65 |
+
$args = array(
|
66 |
+
'headers' => array(
|
67 |
+
'Authorization' => "Bearer MTIzNA==",
|
68 |
+
'Content-Type' => 'application/json'
|
69 |
+
),
|
70 |
+
'method' => 'DELETE',
|
71 |
+
'body' => wp_json_encode($data)
|
72 |
+
);
|
73 |
+
|
74 |
+
// Send remote request
|
75 |
+
$request = wp_remote_request($url, $args);
|
76 |
+
|
77 |
+
// Retrieve information
|
78 |
+
$response_code = wp_remote_retrieve_response_code($request);
|
79 |
+
$response_message = wp_remote_retrieve_response_message($request);
|
80 |
+
$response_body = json_decode(wp_remote_retrieve_body($request));
|
81 |
+
|
82 |
+
if((isset($response_body->error) && $response_body->error == '')){
|
83 |
+
$message = $response_body->message;
|
84 |
+
echo json_encode(['status' => 'success', 'message' => $message]);
|
85 |
+
// return new WP_REST_Response(
|
86 |
+
// array(
|
87 |
+
// 'status' => $response_code,
|
88 |
+
// 'message' => $response_message,
|
89 |
+
// 'data' => $response_body->data
|
90 |
+
// )
|
91 |
+
// );
|
92 |
+
}else{
|
93 |
+
$message = is_array($response_body->errors) ? $response_body->errors[0] : "Face some unprocessable entity";
|
94 |
+
echo json_encode(['status' => 'error', 'message' => $message]);
|
95 |
+
// return new WP_Error($response_code, $response_message, $response_body);
|
96 |
+
}
|
97 |
+
|
98 |
+
// echo json_encode( $categories );
|
99 |
+
}
|
100 |
+
|
101 |
+
// IMPORTANT: don't forget to exit
|
102 |
+
exit;
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Update the campaign status pause/active
|
107 |
+
*/
|
108 |
+
public function tvcajax_update_campaign_status(){
|
109 |
+
// make sure this call is legal
|
110 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'campaignStatusNonce'), 'tvcajax-update-campaign-status-nonce')){
|
111 |
+
|
112 |
+
if(!class_exists('ShoppingApi')){
|
113 |
+
//require_once(__DIR__ . '/ShoppingApi.php');
|
114 |
+
include(ENHANCAD_PLUGIN_DIR . 'includes/setup/ShoppingApi.php');
|
115 |
+
}
|
116 |
+
|
117 |
+
$merchantId = filter_input(INPUT_POST, 'merchantId');
|
118 |
+
$customerId = filter_input(INPUT_POST, 'customerId');
|
119 |
+
$campaignId = filter_input(INPUT_POST, 'campaignId');
|
120 |
+
$budgetId = filter_input(INPUT_POST, 'budgetId');
|
121 |
+
$campaignName = filter_input(INPUT_POST, 'campaignName');
|
122 |
+
$budget = filter_input(INPUT_POST, 'budget');
|
123 |
+
$status = filter_input(INPUT_POST, 'status');
|
124 |
+
$url = 'https://connect.tatvic.com/laravelapi/public/api/campaigns/update';
|
125 |
+
$shoppingObj = new ShoppingApi();
|
126 |
+
$campaignData = $shoppingObj->getCampaignDetails($campaignId);
|
127 |
+
|
128 |
+
$data = [
|
129 |
+
'merchant_id' => $merchantId,
|
130 |
+
'customer_id' => $customerId,
|
131 |
+
'campaign_id' => $campaignId,
|
132 |
+
'account_budget_id' => $budgetId,
|
133 |
+
'campaign_name' => $campaignName,
|
134 |
+
'budget' => $budget,
|
135 |
+
'status' => $status,
|
136 |
+
'target_country' => $campaignData->data['data']->targetCountry,
|
137 |
+
'ad_group_id' => $campaignData->data['data']->adGroupId,
|
138 |
+
'ad_group_resource_name' => $campaignData->data['data']->adGroupResourceName
|
139 |
+
];
|
140 |
+
|
141 |
+
$args = array(
|
142 |
+
'headers' => array(
|
143 |
+
'Authorization' => "Bearer MTIzNA==",
|
144 |
+
'Content-Type' => 'application/json'
|
145 |
+
),
|
146 |
+
'method' => 'PATCH',
|
147 |
+
'body' => wp_json_encode($data)
|
148 |
+
);
|
149 |
+
|
150 |
+
// Send remote request
|
151 |
+
$request = wp_remote_request($url, $args);
|
152 |
+
|
153 |
+
// Retrieve information
|
154 |
+
$response_code = wp_remote_retrieve_response_code($request);
|
155 |
+
$response_message = wp_remote_retrieve_response_message($request);
|
156 |
+
$response_body = json_decode(wp_remote_retrieve_body($request));
|
157 |
+
if((isset($response_body->error) && $response_body->error == '')){
|
158 |
+
$message = $response_body->message;
|
159 |
+
echo json_encode(['status' => 'success', 'message' => $message]);
|
160 |
+
// return new WP_REST_Response(
|
161 |
+
// array(
|
162 |
+
// 'status' => $response_code,
|
163 |
+
// 'message' => $response_message,
|
164 |
+
// 'data' => $response_body->data
|
165 |
+
// )
|
166 |
+
// );
|
167 |
+
}else{
|
168 |
+
$message = is_array($response_body->errors) ? $response_body->errors[0] : "Face some unprocessable entity";
|
169 |
+
echo json_encode(['status' => 'error', 'message' => $message]);
|
170 |
+
// return new WP_Error($response_code, $response_message, $response_body);
|
171 |
+
}
|
172 |
+
|
173 |
+
// echo json_encode( $categories );
|
174 |
+
}
|
175 |
+
|
176 |
+
// IMPORTANT: don't forget to exit
|
177 |
+
exit;
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Returns the campaign categories from a selected country
|
182 |
+
*/
|
183 |
+
public function tvcajax_get_campaign_categories(){
|
184 |
+
// make sure this call is legal
|
185 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'campaignCategoryListsNonce'), 'tvcajax-campaign-category-lists-nonce')){
|
186 |
+
|
187 |
+
$country_code = filter_input(INPUT_POST, 'countryCode');
|
188 |
+
$customer_id = filter_input(INPUT_POST, 'customerId');
|
189 |
+
$url = 'https://connect.tatvic.com/laravelapi/public/api/products/categories';
|
190 |
+
|
191 |
+
$data = [
|
192 |
+
'customer_id' => $customer_id,
|
193 |
+
'country_code' => $country_code
|
194 |
+
];
|
195 |
+
|
196 |
+
$args = array(
|
197 |
+
'headers' => array(
|
198 |
+
'Authorization' => "Bearer MTIzNA==",
|
199 |
+
'Content-Type' => 'application/json'
|
200 |
+
),
|
201 |
+
'body' => wp_json_encode($data)
|
202 |
+
);
|
203 |
+
|
204 |
+
// Send remote request
|
205 |
+
$request = wp_remote_post($url, $args);
|
206 |
+
|
207 |
+
// Retrieve information
|
208 |
+
$response_code = wp_remote_retrieve_response_code($request);
|
209 |
+
$response_message = wp_remote_retrieve_response_message($request);
|
210 |
+
$response_body = json_decode(wp_remote_retrieve_body($request));
|
211 |
+
|
212 |
+
if((isset($response_body->error) && $response_body->error == '')){
|
213 |
+
echo json_encode($response_body->data);
|
214 |
+
// return new WP_REST_Response(
|
215 |
+
// array(
|
216 |
+
// 'status' => $response_code,
|
217 |
+
// 'message' => $response_message,
|
218 |
+
// 'data' => $response_body->data
|
219 |
+
// )
|
220 |
+
// );
|
221 |
+
}else{
|
222 |
+
echo json_encode([]);
|
223 |
+
// return new WP_Error($response_code, $response_message, $response_body);
|
224 |
+
}
|
225 |
+
|
226 |
+
// echo json_encode( $categories );
|
227 |
+
}
|
228 |
+
|
229 |
+
// IMPORTANT: don't forget to exit
|
230 |
+
exit;
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Returns the sub-categories from a selected category
|
235 |
+
*/
|
236 |
+
public function tvcajax_read_next_categories(){
|
237 |
+
// make sure this call is legal
|
238 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'nextCategoryNonce'), 'tvcajax-next-category-nonce')){
|
239 |
+
$file_class = new TVC_File();
|
240 |
+
|
241 |
+
$channel_id = filter_input(INPUT_POST, 'channelId');
|
242 |
+
$requested_level = filter_input(INPUT_POST, 'requestedLevel');
|
243 |
+
$parent_category = filter_input(INPUT_POST, 'parentCategory');
|
244 |
+
$file_language = filter_input(INPUT_POST, 'fileLanguage');
|
245 |
+
$categories = $file_class->get_categories_for_list($channel_id, $requested_level, $parent_category, $file_language);
|
246 |
+
|
247 |
+
if(!is_array($categories)){
|
248 |
+
if('0' === substr($categories, - 1)){
|
249 |
+
chop($categories, '0');
|
250 |
+
}
|
251 |
+
}
|
252 |
+
|
253 |
+
echo json_encode($categories);
|
254 |
+
}
|
255 |
+
|
256 |
+
// IMPORTANT: don't forget to exit
|
257 |
+
exit;
|
258 |
+
}
|
259 |
+
|
260 |
+
/**
|
261 |
+
* Read the category list
|
262 |
+
*/
|
263 |
+
public function tvcajax_read_category_lists(){
|
264 |
+
// make sure this call is legal
|
265 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'categoryListsNonce'), 'tvcajax-category-lists-nonce')){
|
266 |
+
$file_class = new TVC_File();
|
267 |
+
|
268 |
+
$channel_id = filter_input(INPUT_POST, 'channelId');
|
269 |
+
$main_categories_string = filter_input(INPUT_POST, 'mainCategories');
|
270 |
+
$file_language = filter_input(INPUT_POST, 'fileLanguage');
|
271 |
+
$categories_array = explode(' > ', $main_categories_string);
|
272 |
+
$categories = array();
|
273 |
+
$required_levels = count($categories_array) > 0 ? ( count($categories_array) + 1 ) : count($categories_array);
|
274 |
+
|
275 |
+
for($i = 0; $i < $required_levels; $i ++){
|
276 |
+
$parent_category = $i > 0 ? $categories_array[$i - 1] : '';
|
277 |
+
$c = $file_class->get_categories_for_list($channel_id, $i, $parent_category, $file_language);
|
278 |
+
if($c){
|
279 |
+
array_push($categories, $c);
|
280 |
+
}
|
281 |
+
}
|
282 |
+
|
283 |
+
echo json_encode($categories);
|
284 |
+
}
|
285 |
+
|
286 |
+
// IMPORTANT: don't forget to exit
|
287 |
+
exit;
|
288 |
+
}
|
289 |
+
|
290 |
+
/**
|
291 |
+
* Delete a specific feed file
|
292 |
+
*/
|
293 |
+
public function tvcajax_delete_feed_file(){
|
294 |
+
// make sure this call is legal
|
295 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'deleteFeedNonce'), 'tvcajax-delete-feed-nonce')){
|
296 |
+
$file_name = filter_input(INPUT_POST, 'fileTitle');
|
297 |
+
|
298 |
+
if(file_exists(WP_PLUGIN_DIR . '/tvc-product-feed-manager-support/feeds/' . $file_name)){
|
299 |
+
$file = WP_PLUGIN_DIR . '/tvc-product-feed-manager-support/feeds/' . $file_name;
|
300 |
+
}else{
|
301 |
+
$file = TVC_FEEDS_DIR . '/' . $file_name;
|
302 |
+
}
|
303 |
+
|
304 |
+
// only return results when the user is an admin with manage options
|
305 |
+
if(is_admin()){
|
306 |
+
/* translators: %s: Title of the feed file */
|
307 |
+
echo file_exists($file) ? unlink($file) : tvc_show_wp_error(sprintf(esc_html__('Could not find file %s.', 'tvc-product-feed-manager'), $file));
|
308 |
+
}else{
|
309 |
+
echo tvc_show_wp_error(esc_html__('Error deleting the feed. You do not have the correct authorities to delete the file.', 'tvc-product-feed-manager'));
|
310 |
+
}
|
311 |
+
}
|
312 |
+
|
313 |
+
// IMPORTANT: don't forget to exit
|
314 |
+
exit;
|
315 |
+
}
|
316 |
+
|
317 |
+
/**
|
318 |
+
* This function fetches the posted data and triggers the update of the feed file on the server.
|
319 |
+
*/
|
320 |
+
public function tvcajax_update_feed_file(){
|
321 |
+
// make sure this call is legal
|
322 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'updateFeedFileNonce'), 'tvcajax-update-feed-file-nonce')){
|
323 |
+
|
324 |
+
// fetch the data from $_POST
|
325 |
+
$feed_id = filter_input(INPUT_POST, 'feedId');
|
326 |
+
$background_mode_disabled = get_option('tvc_disabled_background_mode', 'false');
|
327 |
+
|
328 |
+
TVC_Feed_Controller::add_id_to_feed_queue($feed_id);
|
329 |
+
|
330 |
+
// if there is no feed processing in progress, of background processing is switched off, start updating the current feed
|
331 |
+
if(!TVC_Feed_Controller::feed_is_processing() || 'true' === $background_mode_disabled){
|
332 |
+
do_action('tvc_manual_feed_update_activated', $feed_id);
|
333 |
+
|
334 |
+
$feed_master_class = new TVC_Feed_Master_Class($feed_id);
|
335 |
+
$feed_master_class->update_feed_file(false);
|
336 |
+
}else{
|
337 |
+
$data_class = new TVC_Data();
|
338 |
+
$data_class->update_feed_status($feed_id, 4); // feed status to waiting in queue
|
339 |
+
echo 'pushed_to_queue';
|
340 |
+
}
|
341 |
+
}
|
342 |
+
|
343 |
+
// IMPORTANT: don't forget to exit
|
344 |
+
exit;
|
345 |
+
}
|
346 |
+
|
347 |
+
/**
|
348 |
+
* Logs a message from a javascript call to the server
|
349 |
+
*/
|
350 |
+
public function tvcajax_log_message(){
|
351 |
+
// make sure this call is legal
|
352 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'logMessageNonce'), 'tvcajax-log-message-nonce')){
|
353 |
+
// fetch the data from $_POST
|
354 |
+
$message = filter_input(INPUT_POST, 'messageList');
|
355 |
+
$file_name = filter_input(INPUT_POST, 'fileName');
|
356 |
+
$text_message = strip_tags($message);
|
357 |
+
|
358 |
+
// only return results when the user is an admin with manage options
|
359 |
+
if(is_admin()){
|
360 |
+
//tvc_write_log_file( $text_message, $file_name );
|
361 |
+
}else{
|
362 |
+
echo tvc_show_wp_error(esc_html__('Error writing the feed. You do not have the correct authorities to write the file.', 'tvc-product-feed-manager'));
|
363 |
+
}
|
364 |
+
}
|
365 |
+
|
366 |
+
// IMPORTANT: don't forget to exit
|
367 |
+
exit;
|
368 |
+
}
|
369 |
+
|
370 |
+
/**
|
371 |
+
* Changes the Auto Feed Fix setting from the Settings page
|
372 |
+
*
|
373 |
+
* @since 1.7.0
|
374 |
+
*/
|
375 |
+
public function tvcajax_auto_feed_fix_mode_selection(){
|
376 |
+
// make sure this call is legal
|
377 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'updateAutoFeedFixNonce'), 'tvcajax-auto-feed-fix-nonce')){
|
378 |
+
$selection = filter_input(INPUT_POST, 'fix_selection');
|
379 |
+
update_option('tvc_auto_feed_fix', $selection);
|
380 |
+
|
381 |
+
echo get_option('tvc_auto_feed_fix');
|
382 |
+
}
|
383 |
+
|
384 |
+
// IMPORTANT: don't forget to exit
|
385 |
+
exit;
|
386 |
+
}
|
387 |
+
|
388 |
+
/**
|
389 |
+
* Changes the Disable Background processing setting from the Settings page
|
390 |
+
*
|
391 |
+
* @since 2.0.7
|
392 |
+
*/
|
393 |
+
public function tvcajax_background_processing_mode_selection(){
|
394 |
+
// make sure this call is legal
|
395 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'backgroundModeNonce'), 'tvcajax-background-mode-nonce')){
|
396 |
+
$selection = filter_input(INPUT_POST, 'mode_selection');
|
397 |
+
update_option('tvc_disabled_background_mode', $selection);
|
398 |
+
|
399 |
+
echo get_option('tvc_disabled_background_mode');
|
400 |
+
}
|
401 |
+
|
402 |
+
// IMPORTANT: don't forget to exit
|
403 |
+
exit;
|
404 |
+
}
|
405 |
+
|
406 |
+
/**
|
407 |
+
* Changes the Feed Process Logger setting from the Settings page.
|
408 |
+
*
|
409 |
+
* @since 2.8.0
|
410 |
+
*/
|
411 |
+
public function tvcajax_feed_logger_status_selection(){
|
412 |
+
// make sure this call is legal
|
413 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'feedLoggerStatusNonce'), 'tvcajax-logger-status-nonce')){
|
414 |
+
$selection = filter_input(INPUT_POST, 'statusSelection');
|
415 |
+
update_option('tvc_process_logger_status', $selection);
|
416 |
+
|
417 |
+
echo get_option('tvc_process_logger_status');
|
418 |
+
}
|
419 |
+
|
420 |
+
// IMPORTANT: don't forget to exit
|
421 |
+
exit;
|
422 |
+
}
|
423 |
+
|
424 |
+
/**
|
425 |
+
* Changes the Show Product Identifiers setting from the Settings page.
|
426 |
+
*
|
427 |
+
* @since 2.10.0
|
428 |
+
*/
|
429 |
+
public function tvcajax_show_product_identifiers_selection(){
|
430 |
+
// make sure this call is legal
|
431 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'showPINonce'), 'tvcajax-show-pi-nonce')){
|
432 |
+
$selection = filter_input(INPUT_POST, 'showPiSelection');
|
433 |
+
update_option('tvc_show_product_identifiers', $selection);
|
434 |
+
|
435 |
+
echo get_option('tvc_show_product_identifiers');
|
436 |
+
}
|
437 |
+
|
438 |
+
// IMPORTANT: don't forget to exit
|
439 |
+
exit;
|
440 |
+
}
|
441 |
+
|
442 |
+
/**
|
443 |
+
* Changes the Debug setting from the Settings page
|
444 |
+
*
|
445 |
+
* @since 1.9.0
|
446 |
+
*/
|
447 |
+
public function tvcajax_debug_mode_selection(){
|
448 |
+
// make sure this call is legal
|
449 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'debugNonce'), 'tvcajax-debug-nonce')){
|
450 |
+
$selection = filter_input(INPUT_POST, 'debug_selection');
|
451 |
+
update_option('tvc_debug_mode', $selection);
|
452 |
+
|
453 |
+
echo get_option('tvc_debug_mode');
|
454 |
+
}
|
455 |
+
|
456 |
+
// IMPORTANT: don't forget to exit
|
457 |
+
exit;
|
458 |
+
}
|
459 |
+
|
460 |
+
public function tvcajax_set_third_party_attribute_keywords(){
|
461 |
+
// make sure this call is legal
|
462 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'thirdPartyKeywordsNonce'), 'tvcajax-set-third-party-keywords-nonce')){
|
463 |
+
$keywords = filter_input(INPUT_POST, 'keywords');
|
464 |
+
update_option('tvc_third_party_attribute_keywords', $keywords);
|
465 |
+
|
466 |
+
echo get_option('tvc_third_party_attribute_keywords');
|
467 |
+
}
|
468 |
+
|
469 |
+
// IMPORTANT: don't forget to exit
|
470 |
+
exit;
|
471 |
+
}
|
472 |
+
|
473 |
+
public function tvcajax_set_notice_mailaddress(){
|
474 |
+
// make sure this call is legal
|
475 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'noticeMailaddressNonce'), 'tvcajax-set-notice-mailaddress-nonce')){
|
476 |
+
$mailaddress = filter_input(INPUT_POST, 'mailaddress');
|
477 |
+
update_option('tvc_notice_mailaddress', $mailaddress);
|
478 |
+
|
479 |
+
echo get_option('tvc_notice_mailaddress');
|
480 |
+
}
|
481 |
+
|
482 |
+
// IMPORTANT: don't forget to exit
|
483 |
+
exit;
|
484 |
+
}
|
485 |
+
|
486 |
+
/**
|
487 |
+
* Re-initiates the plugin, updates the database and loads all cron jobs
|
488 |
+
*
|
489 |
+
* @since 1.9.0
|
490 |
+
*/
|
491 |
+
public function tvcajax_reinitiate_plugin(){
|
492 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'reInitiateNonce'), 'tvcajax-reinitiate-nonce')){
|
493 |
+
|
494 |
+
if(tvc_reinitiate_plugin()){
|
495 |
+
echo 'Plugin re-initiated';
|
496 |
+
}else{
|
497 |
+
echo 'Re-initiation failed!';
|
498 |
+
}
|
499 |
+
}
|
500 |
+
|
501 |
+
// IMPORTANT: don't forget to exit
|
502 |
+
exit;
|
503 |
+
}
|
504 |
+
|
505 |
+
/**
|
506 |
+
* Clears all option data that is related to the feed processing
|
507 |
+
*
|
508 |
+
* @since 1.10.0
|
509 |
+
*/
|
510 |
+
public function tvcajax_clear_feed_process_data(){
|
511 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'clearFeedNonce'), 'tvcajax-clear-feed-nonce')){
|
512 |
+
|
513 |
+
if(tvc_clear_feed_process_data()){
|
514 |
+
echo esc_html__('Feed processing data cleared', 'tvc-product-feed-manager');
|
515 |
+
}else{
|
516 |
+
/* translators: clearing the feed data failed */
|
517 |
+
echo esc_html__('Clearing failed!', 'tvc-product-feed-manager');
|
518 |
+
}
|
519 |
+
}
|
520 |
+
|
521 |
+
// IMPORTANT: don't forget to exit
|
522 |
+
exit;
|
523 |
+
}
|
524 |
+
|
525 |
+
/**
|
526 |
+
* Returns the campaign categories from a selected country
|
527 |
+
*/
|
528 |
+
public function tvcajax_get_gmc_categories(){
|
529 |
+
// make sure this call is legal
|
530 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'gmcCategoryListsNonce'), 'tvcajax-gmc-category-lists-nonce')){
|
531 |
+
|
532 |
+
$country_code = filter_input(INPUT_POST, 'countryCode');
|
533 |
+
$customer_id = filter_input(INPUT_POST, 'customerId');
|
534 |
+
$parent = filter_input(INPUT_POST, 'parent');
|
535 |
+
//$url = 'https://connect.tatvic.com/laravelapi/public/api/products/gmc-categories';
|
536 |
+
//$url = 'http://127.0.0.1:8000/api/products/gmc-categories';
|
537 |
+
$url = 'https://connect.tatvic.com/laravelapi/public/api/products/gmc-categories';
|
538 |
+
|
539 |
+
$data = [
|
540 |
+
'customer_id' => $customer_id,
|
541 |
+
'country_code' => $country_code,
|
542 |
+
'parent' => $parent
|
543 |
+
];
|
544 |
+
|
545 |
+
$args = array(
|
546 |
+
'headers' => array(
|
547 |
+
'Authorization' => "Bearer MTIzNA==",
|
548 |
+
'Content-Type' => 'application/json'
|
549 |
+
),
|
550 |
+
'body' => wp_json_encode($data)
|
551 |
+
);
|
552 |
+
|
553 |
+
// Send remote request
|
554 |
+
$request = wp_remote_post($url, $args);
|
555 |
+
|
556 |
+
// Retrieve information
|
557 |
+
$response_code = wp_remote_retrieve_response_code($request);
|
558 |
+
$response_message = wp_remote_retrieve_response_message($request);
|
559 |
+
$response_body = json_decode(wp_remote_retrieve_body($request));
|
560 |
+
|
561 |
+
if((isset($response_body->error) && $response_body->error == '')){
|
562 |
+
echo json_encode($response_body->data);
|
563 |
+
// return new WP_REST_Response(
|
564 |
+
// array(
|
565 |
+
// 'status' => $response_code,
|
566 |
+
// 'message' => $response_message,
|
567 |
+
// 'data' => $response_body->data
|
568 |
+
// )
|
569 |
+
// );
|
570 |
+
}else{
|
571 |
+
echo json_encode([]);
|
572 |
+
// return new WP_Error($response_code, $response_message, $response_body);
|
573 |
+
}
|
574 |
+
|
575 |
+
// echo json_encode( $categories );
|
576 |
+
}
|
577 |
+
|
578 |
+
// IMPORTANT: don't forget to exit
|
579 |
+
exit;
|
580 |
+
}
|
581 |
+
|
582 |
+
public function getPostMetaData($id){
|
583 |
+
$queries = new TVC_Queries();
|
584 |
+
$column2 = json_decode(json_encode($queries->getTablePostMeta($id)), true);
|
585 |
+
$arr = array();
|
586 |
+
foreach($column2 as $val){
|
587 |
+
$arr[$val['meta_key']] = $val['meta_value'];
|
588 |
+
}
|
589 |
+
return $arr;
|
590 |
+
}
|
591 |
+
|
592 |
+
/**
|
593 |
+
* create product batch for product sync up
|
594 |
+
*/
|
595 |
+
public function tvcajax_product_syncup(){
|
596 |
+
// make sure this call is legal
|
597 |
+
|
598 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'productSyncupNonce'), 'tvcajax-product-syncup-nonce')){
|
599 |
+
|
600 |
+
|
601 |
+
if(!class_exists('CustomApi')){
|
602 |
+
include(ENHANCAD_PLUGIN_DIR . 'includes/setup/CustomApi.php');
|
603 |
+
}
|
604 |
+
$customObj = new CustomApi();
|
605 |
+
|
606 |
+
$batchId = time();
|
607 |
+
$merchantId = filter_input(INPUT_POST, 'merchantId');
|
608 |
+
$customerId = filter_input(INPUT_POST, 'customerId');
|
609 |
+
$accountId = filter_input(INPUT_POST, 'accountId');
|
610 |
+
$subscriptionId = filter_input(INPUT_POST, 'subscriptionId');
|
611 |
+
$platformCustomerId = filter_input(INPUT_POST, 'platformCustomerId');
|
612 |
+
$data = filter_input(INPUT_POST, 'data');
|
613 |
+
/* echo "=============="; */
|
614 |
+
// echo "<pre>";
|
615 |
+
parse_str($data, $formArray);
|
616 |
+
//print_r($formArray); // Only for print array
|
617 |
+
$mappedCatsDB = [];
|
618 |
+
$mappedCats = [];
|
619 |
+
$mappedAttrs = [];
|
620 |
+
foreach($formArray as $key => $value){
|
621 |
+
if(preg_match("/^category-name-/i", $key)){
|
622 |
+
if($value != ''){
|
623 |
+
$keyArray = explode("name-", $key);
|
624 |
+
$mappedCatsDB[$keyArray[1]]['name'] = $value;
|
625 |
+
}
|
626 |
+
}else if(preg_match("/^category-/i", $key)){
|
627 |
+
if($value != '' && $value > 0){
|
628 |
+
$keyArray = explode("-", $key);
|
629 |
+
$mappedCats[$keyArray[1]] = $value;
|
630 |
+
$mappedCatsDB[$keyArray[1]]['id'] = $value;
|
631 |
+
}
|
632 |
+
}else{
|
633 |
+
if($value){
|
634 |
+
$mappedAttrs[$key] = $value;
|
635 |
+
}
|
636 |
+
}
|
637 |
+
}
|
638 |
+
update_option("ee_prod_mapped_cats", serialize($mappedCatsDB));
|
639 |
+
update_option("ee_prod_mapped_attrs", serialize($mappedAttrs));
|
640 |
+
|
641 |
+
if(!empty($mappedCats)){
|
642 |
+
$catMapRequest = [];
|
643 |
+
$catMapRequest['subscription_id'] = $subscriptionId;
|
644 |
+
$catMapRequest['customer_id'] = $customerId;
|
645 |
+
$catMapRequest['merchant_id'] = $merchantId;
|
646 |
+
$catMapRequest['category'] = $mappedCats;
|
647 |
+
$catMapResponse = $customObj->setGmcCategoryMapping($catMapRequest);
|
648 |
+
}
|
649 |
+
|
650 |
+
if(!empty($mappedAttrs)){
|
651 |
+
$attrMapRequest = [];
|
652 |
+
$attrMapRequest['subscription_id'] = $subscriptionId;
|
653 |
+
$attrMapRequest['customer_id'] = $customerId;
|
654 |
+
$attrMapRequest['merchant_id'] = $merchantId;
|
655 |
+
$attrMapRequest['attribute'] = $mappedAttrs;
|
656 |
+
$attrMapResponse = $customObj->setGmcAttributeMapping($attrMapRequest);
|
657 |
+
}
|
658 |
+
|
659 |
+
$entries = [];
|
660 |
+
if(!empty($mappedCats)){
|
661 |
+
foreach($mappedCats as $key => $mappedCat){
|
662 |
+
$all_products = get_posts(array(
|
663 |
+
'post_type' => 'product',
|
664 |
+
'numberposts' => -1,
|
665 |
+
'post_status' => 'publish',
|
666 |
+
'tax_query' => array(
|
667 |
+
array(
|
668 |
+
'taxonomy' => 'product_cat',
|
669 |
+
'field' => 'term_id',
|
670 |
+
'terms' => $key, /* category name */
|
671 |
+
'operator' => 'IN',
|
672 |
+
)
|
673 |
+
),'meta_query' => array(
|
674 |
+
'relation' => 'AND',
|
675 |
+
array(
|
676 |
+
'key' => '_stock_status',
|
677 |
+
'value' => 'instock'
|
678 |
+
),
|
679 |
+
array(
|
680 |
+
'relation' => 'or',
|
681 |
+
array(
|
682 |
+
'key' => '_sale_price',
|
683 |
+
'value' => '',
|
684 |
+
'compare' => '!=',
|
685 |
+
),
|
686 |
+
array(
|
687 |
+
'key' => '_price',
|
688 |
+
'value' => '',
|
689 |
+
'compare' => '!=',
|
690 |
+
)
|
691 |
+
)
|
692 |
+
)
|
693 |
+
));
|
694 |
+
foreach($all_products as $postkey => $postvalue){
|
695 |
+
$postmeta = [];
|
696 |
+
$postmeta = $this->getPostMetaData($postvalue->ID);
|
697 |
+
$prd = wc_get_product($postvalue->ID);
|
698 |
+
$postObj = (object) array_merge((array) $postvalue, (array) $postmeta);
|
699 |
+
$product = [];
|
700 |
+
foreach($formArray as $key => $value){
|
701 |
+
|
702 |
+
// $product['content_language'] = 'en';
|
703 |
+
// $product['target_country'] = 'US';
|
704 |
+
$product['channel'] = 'online';
|
705 |
+
$product['google_product_category'] = $mappedCat;
|
706 |
+
$product['link'] = get_permalink($postvalue->ID);
|
707 |
+
if($key == 'image_link'){
|
708 |
+
$image_id = $prd->get_image_id();
|
709 |
+
$product['image_link'] = wp_get_attachment_image_url($image_id, 'full');
|
710 |
+
}else if($key == 'price'){
|
711 |
+
$product[$key]['value'] = $postObj->_price;
|
712 |
+
$product[$key]['currency'] = (get_option('woocommerce_currency') != '' ? get_option('woocommerce_currency') : 'USD');
|
713 |
+
}else if($key == 'sale_price'){
|
714 |
+
$product[$key]['value'] = $postObj->_sale_price;
|
715 |
+
$product[$key]['currency'] = (get_option('woocommerce_currency') != '' ? get_option('woocommerce_currency') : 'USD');
|
716 |
+
}else if($key == 'target_country'){
|
717 |
+
$product[$key] = ($postObj->$value != '' ? $postObj->$value : (isset($this->woo_country()[0]) ? $this->woo_country()[0] : ''));
|
718 |
+
//$product[$key] = ($postObj->$value != '' ? $postObj->$value : get_option('woocommerce_default_country'));
|
719 |
+
}else if($key == 'content_language'){
|
720 |
+
$product[$key] = ($postObj->$value != '' ? $postObj->$value : 'en');
|
721 |
+
}else if(isset($postObj->$value)){
|
722 |
+
// echo $product[$key]."==".$postObj->$value."<br>";
|
723 |
+
$product[$key] = $postObj->$value;
|
724 |
+
}
|
725 |
+
}
|
726 |
+
|
727 |
+
$entrie = [
|
728 |
+
'merchant_id' => $merchantId,
|
729 |
+
'batch_id' => ++$batchId,
|
730 |
+
'method' => 'insert',
|
731 |
+
'product' => $product
|
732 |
+
];
|
733 |
+
$entries[] = $entrie;
|
734 |
+
}
|
735 |
+
|
736 |
+
wp_reset_query();
|
737 |
+
}
|
738 |
+
}else{
|
739 |
+
$qArgs = array(
|
740 |
+
'post_type' => 'product',
|
741 |
+
'post_status' => 'publish',
|
742 |
+
'meta_query' => array(
|
743 |
+
'relation' => 'AND',
|
744 |
+
array(
|
745 |
+
'key' => '_stock_status',
|
746 |
+
'value' => 'instock'
|
747 |
+
),
|
748 |
+
array(
|
749 |
+
'relation' => 'or',
|
750 |
+
array(
|
751 |
+
'key' => '_sale_price',
|
752 |
+
'value' => '',
|
753 |
+
'compare' => '!=',
|
754 |
+
),
|
755 |
+
array(
|
756 |
+
'key' => '_price',
|
757 |
+
'value' => '',
|
758 |
+
'compare' => '!=',
|
759 |
+
)
|
760 |
+
)
|
761 |
+
)
|
762 |
+
);
|
763 |
+
$loop = new WP_Query($qArgs);
|
764 |
+
foreach($loop->posts as $postkey => $postvalue){
|
765 |
+
$postmeta = [];
|
766 |
+
$postmeta = $this->getPostMetaData($postvalue->ID);
|
767 |
+
$postObj = (object) array_merge((array) $postvalue, (array) $postmeta);
|
768 |
+
|
769 |
+
$product = [];
|
770 |
+
foreach($formArray as $key => $value){
|
771 |
+
$product['content_language'] = 'en';
|
772 |
+
//$product['target_country'] = 'US';
|
773 |
+
$product['target_country'] = (isset($this->woo_country()[0]) ? $this->woo_country()[0] : '');
|
774 |
+
$product['channel'] = 'online';
|
775 |
+
if($key == 'price'){
|
776 |
+
$product[$key]['value'] = $postObj->_price;
|
777 |
+
// $product[$key]['currency'] = 'USD';
|
778 |
+
$product[$key]['currency'] = (get_option('woocommerce_currency') != '' ? get_option('woocommerce_currency') : 'USD');
|
779 |
+
}else if($key == 'sale_price'){
|
780 |
+
$product[$key]['value'] = $postObj->_sale_price;
|
781 |
+
//$product[$key]['currency'] = 'USD';
|
782 |
+
$product[$key]['currency'] = (get_option('woocommerce_currency') != '' ? get_option('woocommerce_currency') : 'USD');
|
783 |
+
}else if($key == 'target_country'){
|
784 |
+
$product[$key] = ($postObj->$value != '' ? $postObj->$value : (isset($this->woo_country()[0]) ? $this->woo_country()[0] : ''));
|
785 |
+
}else if(isset($postObj->$value)){
|
786 |
+
$product[$key] = $postObj->$value;
|
787 |
+
}
|
788 |
+
}
|
789 |
+
|
790 |
+
$entrie = [
|
791 |
+
'merchant_id' => $merchantId,
|
792 |
+
'batch_id' => ++$batchId,
|
793 |
+
'method' => 'insert',
|
794 |
+
'product' => $product
|
795 |
+
];
|
796 |
+
$entries[] = $entrie;
|
797 |
+
}
|
798 |
+
wp_reset_query();
|
799 |
+
}
|
800 |
+
|
801 |
+
$data = [
|
802 |
+
'merchant_id' => $accountId,
|
803 |
+
'account_id' => $merchantId,
|
804 |
+
//'platform_customer_id' => $platformCustomerId,
|
805 |
+
'subscription_id' => $subscriptionId,
|
806 |
+
'entries' => $entries,
|
807 |
+
];
|
808 |
+
|
809 |
+
$url = 'https://connect.tatvic.com/laravelapi/public/api/products/batch';
|
810 |
+
//$url = 'http://127.0.0.1:8000/api/products/batch';
|
811 |
+
|
812 |
+
$args = array(
|
813 |
+
'headers' => array(
|
814 |
+
'Authorization' => "Bearer MTIzNA==",
|
815 |
+
'Content-Type' => 'application/json',
|
816 |
+
'AccessToken' => $this->generateAccessToken($_SESSION['access_token'], $_SESSION['refresh_token'])
|
817 |
+
),
|
818 |
+
'body' => wp_json_encode($data)
|
819 |
+
);
|
820 |
+
|
821 |
+
// Send remote request
|
822 |
+
/* echo "<pre>";
|
823 |
+
print_r($args); */
|
824 |
+
$request = wp_remote_post($url, $args);
|
825 |
+
|
826 |
+
/* print_r($request); */
|
827 |
+
/* die; */
|
828 |
+
// Retrieve information
|
829 |
+
$response_code = wp_remote_retrieve_response_code($request);
|
830 |
+
$response_message = wp_remote_retrieve_response_message($request);
|
831 |
+
$response_body = json_decode(wp_remote_retrieve_body($request));
|
832 |
+
|
833 |
+
if((isset($response_body->error) && $response_body->error == '')){
|
834 |
+
echo json_encode(['status' => 'success']);
|
835 |
+
// return new WP_REST_Response(
|
836 |
+
// array(
|
837 |
+
// 'status' => $response_code,
|
838 |
+
// 'message' => $response_message,
|
839 |
+
// 'data' => $response_body->data
|
840 |
+
// )
|
841 |
+
// );
|
842 |
+
}else{
|
843 |
+
foreach($response_body->errors as $err){
|
844 |
+
$message = $err;
|
845 |
+
break;
|
846 |
+
}
|
847 |
+
echo json_encode(['status' => 'error', 'message' => $message]);
|
848 |
+
// return new WP_Error($response_code, $response_message, $response_body);
|
849 |
+
}
|
850 |
+
|
851 |
+
// echo json_encode( $categories );
|
852 |
+
}
|
853 |
+
|
854 |
+
// IMPORTANT: don't forget to exit
|
855 |
+
exit;
|
856 |
+
}
|
857 |
+
|
858 |
+
/**
|
859 |
+
* create product batch for product sync up
|
860 |
+
*/
|
861 |
+
public function tvcajax_custom_metrics_dimension(){
|
862 |
+
// make sure this call is legal
|
863 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'customMetricsDimensionNonce'), 'tvcajax-custom-metrics-dimension-nonce')){
|
864 |
+
|
865 |
+
if(!class_exists('CustomApi')){
|
866 |
+
include(ENHANCAD_PLUGIN_DIR . 'includes/setup/CustomApi.php');
|
867 |
+
}
|
868 |
+
$customObj = new CustomApi();
|
869 |
+
|
870 |
+
$accountId = filter_input(INPUT_POST, 'accountId');
|
871 |
+
// $accountId = '184918792';
|
872 |
+
$webPropertyId = filter_input(INPUT_POST, 'webPropertyId');
|
873 |
+
// $webPropertyId = 'UA-184918792-5';
|
874 |
+
$subscriptionId = filter_input(INPUT_POST, 'subscriptionId');
|
875 |
+
$data = filter_input(INPUT_POST, 'data');
|
876 |
+
parse_str($data, $formArray);
|
877 |
+
//print_r($formArray); // Only for print array
|
878 |
+
|
879 |
+
$customDimension = [];
|
880 |
+
$customMetrics = [];
|
881 |
+
$dimensions = [];
|
882 |
+
$metrics = [];
|
883 |
+
|
884 |
+
for($i = 1; $i <= 12; $i++){
|
885 |
+
$dimension['id'] = "";
|
886 |
+
$dimension['index'] = $formArray['did-' . $i];
|
887 |
+
$dimension['active'] = true;
|
888 |
+
$dimension['kind'] = "";
|
889 |
+
$dimension['name'] = $formArray['dname-' . $i];
|
890 |
+
$dimension['scope'] = $formArray['dscope-' . $i];
|
891 |
+
$dimension['created'] = "";
|
892 |
+
$dimension['updated'] = "";
|
893 |
+
$dimension['self_link'] = "";
|
894 |
+
$dimension['parent_link']['href'] = "";
|
895 |
+
$dimension['parent_link']['parent_link_type'] = "";
|
896 |
+
$dimensions[] = $dimension;
|
897 |
+
}
|
898 |
+
|
899 |
+
for($i = 1; $i <= 7; $i++){
|
900 |
+
$metric['id'] = "";
|
901 |
+
$metric['index'] = $formArray['mid-' . $i];
|
902 |
+
$metric['active'] = true;
|
903 |
+
$metric['kind'] = "";
|
904 |
+
$metric['name'] = $formArray['mname-' . $i];
|
905 |
+
$metric['scope'] = $formArray['mscope-' . $i];
|
906 |
+
$metric['created'] = "";
|
907 |
+
$metric['updated'] = "";
|
908 |
+
$metric['self_link'] = "";
|
909 |
+
$metric['max_value'] = "";
|
910 |
+
$metric['min_value'] = "";
|
911 |
+
$metric['type'] = "INTEGER";
|
912 |
+
$metric['parent_link']['href'] = "";
|
913 |
+
$metric['parent_link']['parent_link_type'] = "";
|
914 |
+
$metrics[] = $metric;
|
915 |
+
}
|
916 |
+
|
917 |
+
if(!empty($dimensions)){
|
918 |
+
$dimenRequest = [];
|
919 |
+
$dimenRequest['account_id'] = $accountId;
|
920 |
+
$dimenRequest['web_property_id'] = $webPropertyId;
|
921 |
+
$dimenRequest['subscription_id'] = $subscriptionId;
|
922 |
+
$dimenRequest['data'] = $dimensions;
|
923 |
+
$dimenResponse = $customObj->createCustomDimensions($dimenRequest);
|
924 |
+
}
|
925 |
+
if(!empty($metrics)){
|
926 |
+
$metrRequest = [];
|
927 |
+
$metrRequest['account_id'] = $accountId;
|
928 |
+
$metrRequest['web_property_id'] = $webPropertyId;
|
929 |
+
$metrRequest['subscription_id'] = $subscriptionId;
|
930 |
+
$metrRequest['data'] = $metrics;
|
931 |
+
$metrResponse = $customObj->createCustomMetrics($metrRequest);
|
932 |
+
}
|
933 |
+
|
934 |
+
|
935 |
+
// Retrieve information
|
936 |
+
/* $response_code = wp_remote_retrieve_response_code($request);
|
937 |
+
$response_message = wp_remote_retrieve_response_message($request);
|
938 |
+
$response_body = json_decode(wp_remote_retrieve_body($request)); */
|
939 |
+
|
940 |
+
// print_r($dimenResponse);
|
941 |
+
// echo "=======";
|
942 |
+
// print_r($metrResponse);
|
943 |
+
// exit;
|
944 |
+
|
945 |
+
|
946 |
+
if((isset($dimenResponse->error) && $dimenResponse->error == '' && isset($metrResponse->error) && $metrResponse->error == '')){
|
947 |
+
echo json_encode(['status' => 'success']);
|
948 |
+
// return new WP_REST_Response(
|
949 |
+
// array(
|
950 |
+
// 'status' => $response_code,
|
951 |
+
// 'message' => $response_message,
|
952 |
+
// 'data' => $response_body->data
|
953 |
+
// )
|
954 |
+
// );
|
955 |
+
}else{
|
956 |
+
$metrError = '';
|
957 |
+
$dimenError = '';
|
958 |
+
$message = NULL;
|
959 |
+
if($dimenResponse->errors){
|
960 |
+
/* print_r($dimenResponse->errors); */
|
961 |
+
$dimenError = $dimenResponse->errors[0];
|
962 |
+
$message = str_replace('this entity', 'dimensions ', $dimenError);
|
963 |
+
}
|
964 |
+
if($metrResponse->errors){
|
965 |
+
/* print_r($metrResponse->errors); */
|
966 |
+
$metrError = str_replace('this entity', 'metrics ', $metrResponse->errors[0]);
|
967 |
+
$message = is_null($message) ? $metrError : $message . ' ' . $metrError;
|
968 |
+
}
|
969 |
+
echo json_encode(['status' => 'error', 'message' => $message]);
|
970 |
+
}
|
971 |
+
}
|
972 |
+
|
973 |
+
// IMPORTANT: don't forget to exit
|
974 |
+
exit;
|
975 |
+
}
|
976 |
+
|
977 |
+
public function tvcajax_store_time_taken(){
|
978 |
+
// make sure this call is legal
|
979 |
+
if($this->safe_ajax_call(filter_input(INPUT_POST, 'campaignCategoryListsNonce'), 'tvcajax-store-time-taken-nonce')){
|
980 |
+
$ee_options_data = unserialize(get_option('ee_options'));
|
981 |
+
if(isset($ee_options_data['subscription_id'])) {
|
982 |
+
$ee_subscription_id = $ee_options_data['subscription_id'];
|
983 |
+
} else {
|
984 |
+
$ee_subscription_id = null;
|
985 |
+
}
|
986 |
+
$url = 'https://connect.tatvic.com/laravelapi/public/api/customer-subscriptions/update-setup-time';
|
987 |
+
$data = [
|
988 |
+
'subscription_id' => $ee_subscription_id,
|
989 |
+
'setup_start_time' => date('Y-m-d H:i:s'),
|
990 |
+
];
|
991 |
+
$args = array(
|
992 |
+
'headers' => array(
|
993 |
+
'Authorization' => "Bearer MTIzNA==",
|
994 |
+
'Content-Type' => 'application/json'
|
995 |
+
),
|
996 |
+
'body' => wp_json_encode($data)
|
997 |
+
);
|
998 |
+
// Send remote request
|
999 |
+
$request = wp_remote_post($url, $args);
|
1000 |
+
// Retrieve information
|
1001 |
+
$response_code = wp_remote_retrieve_response_code($request);
|
1002 |
+
$response_message = wp_remote_retrieve_response_message($request);
|
1003 |
+
$response_body = json_decode(wp_remote_retrieve_body($request));
|
1004 |
+
if((isset($response_body->error) && $response_body->error == '')){
|
1005 |
+
echo json_encode($response_body->data);
|
1006 |
+
// return new WP_REST_Response(
|
1007 |
+
// array(
|
1008 |
+
// 'status' => $response_code,
|
1009 |
+
// 'message' => $response_message,
|
1010 |
+
// 'data' => $response_body->data
|
1011 |
+
// )
|
1012 |
+
// );
|
1013 |
+
}else{
|
1014 |
+
echo json_encode([]);
|
1015 |
+
// return new WP_Error($response_code, $response_message, $response_body);
|
1016 |
+
}
|
1017 |
+
|
1018 |
+
// echo json_encode( $categories );
|
1019 |
+
}
|
1020 |
+
|
1021 |
+
// IMPORTANT: don't forget to exit
|
1022 |
+
exit;
|
1023 |
+
}
|
1024 |
+
public function generateAccessToken($access_token, $refresh_token) {
|
1025 |
+
$request = "https://www.googleapis.com/oauth2/v1/tokeninfo?"
|
1026 |
+
. "access_token=" . $access_token;
|
1027 |
+
|
1028 |
+
$ch = curl_init();
|
1029 |
+
curl_setopt($ch, CURLOPT_URL, $request);
|
1030 |
+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
|
1031 |
+
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
|
1032 |
+
$response = curl_exec($ch);
|
1033 |
+
$result = json_decode($response);
|
1034 |
+
|
1035 |
+
if (isset($result->error) && $result->error) {
|
1036 |
+
$credentials_file = ENHANCAD_PLUGIN_DIR . 'includes/setup/json/client-secrets.json';
|
1037 |
+
$str = file_get_contents($credentials_file);
|
1038 |
+
$credentials = $str ? json_decode($str, true) : [];
|
1039 |
+
$url = 'https://www.googleapis.com/oauth2/v4/token';
|
1040 |
+
$header = array("content-type: application/json");
|
1041 |
+
$clientId = $credentials['web']['client_id'];
|
1042 |
+
$clientSecret = $credentials['web']['client_secret'];
|
1043 |
+
$refreshToken = $refresh_token;
|
1044 |
+
$data = [
|
1045 |
+
"grant_type" => 'refresh_token',
|
1046 |
+
"client_id" => $clientId,
|
1047 |
+
'client_secret' => $clientSecret,
|
1048 |
+
'refresh_token' => $refreshToken,
|
1049 |
+
];
|
1050 |
+
|
1051 |
+
$postData = json_encode($data);
|
1052 |
+
$ch = curl_init();
|
1053 |
+
curl_setopt_array($ch, array(
|
1054 |
+
CURLOPT_URL => $url, //esc_url($this->curl_url),
|
1055 |
+
CURLOPT_RETURNTRANSFER => true,
|
1056 |
+
CURLOPT_TIMEOUT => 0,
|
1057 |
+
CURLOPT_HTTPHEADER => $header,
|
1058 |
+
CURLOPT_POSTFIELDS => $postData
|
1059 |
+
));
|
1060 |
+
$response = curl_exec($ch);
|
1061 |
+
$response = json_decode($response);
|
1062 |
+
return $response->access_token;
|
1063 |
+
} else {
|
1064 |
+
return $access_token;
|
1065 |
+
}
|
1066 |
+
}
|
1067 |
+
public function woo_country(){
|
1068 |
+
// The country/state
|
1069 |
+
$store_raw_country = get_option('woocommerce_default_country');
|
1070 |
+
// Split the country/state
|
1071 |
+
$split_country = explode(":", $store_raw_country);
|
1072 |
+
return $split_country;
|
1073 |
+
}
|
1074 |
+
|
1075 |
+
}
|
1076 |
+
|
1077 |
+
// End of TVC_Ajax_File_Class
|
1078 |
+
|
1079 |
+
endif;
|
1080 |
+
|
1081 |
+
$tvcajax_file_class = new TVC_Ajax_File();
|
includes/data/class-tvc-backup.php
ADDED
@@ -0,0 +1,181 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Backup Class.
|
5 |
+
*
|
6 |
+
* @package WP Product Feed Manager/Data/Classes
|
7 |
+
* @version 1.0.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Backup' ) ) :
|
15 |
+
|
16 |
+
class TVC_Backup {
|
17 |
+
|
18 |
+
private $_wpdb;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @var string placeholder containing the wp table prefix
|
22 |
+
*/
|
23 |
+
private $_table_prefix;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* TVC_Queries Constructor
|
27 |
+
*/
|
28 |
+
public function __construct() {
|
29 |
+
// get global WordPress database functions
|
30 |
+
global $wpdb;
|
31 |
+
|
32 |
+
// assign the global wpdb to a variable
|
33 |
+
$this->_wpdb = &$wpdb;
|
34 |
+
|
35 |
+
// assign the wp table prefix to a variable
|
36 |
+
$this->_table_prefix = $this->_wpdb->prefix;
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Reads the data from all plugin related tables ands stores the data in a sql like string
|
41 |
+
* The return string contains a timestamp, the database version, the option settings and the table content
|
42 |
+
*
|
43 |
+
* @since 1.7.0
|
44 |
+
* @return string sql like string with the backup data
|
45 |
+
*/
|
46 |
+
public function read_full_backup_data() {
|
47 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
48 |
+
$meta_table = $this->_table_prefix . 'feedmanager_product_feedmeta';
|
49 |
+
$channel_table = $this->_table_prefix . 'feedmanager_channel';
|
50 |
+
|
51 |
+
$main_table_columns = $this->_wpdb->get_col( "DESC {$main_table}", 0 );
|
52 |
+
$meta_table_columns = $this->_wpdb->get_col( "DESC {$meta_table}", 0 );
|
53 |
+
$channel_table_columns = $this->_wpdb->get_col( "DESC {$channel_table}", 0 );
|
54 |
+
|
55 |
+
$main_table_content = $this->make_table_backup_string( $this->_wpdb->get_results( "SELECT * FROM $main_table", ARRAY_N ), $main_table_columns );
|
56 |
+
$meta_table_content = $this->make_table_backup_string( $this->_wpdb->get_results( "SELECT * FROM $meta_table", ARRAY_N ), $meta_table_columns );
|
57 |
+
$channel_table_content = $this->make_table_backup_string( $this->_wpdb->get_results( "SELECT * FROM $channel_table", ARRAY_N ), $channel_table_columns );
|
58 |
+
|
59 |
+
$db_version = get_option( 'tvc_db_version' );
|
60 |
+
$ftp_passive = 'inactive';
|
61 |
+
$auto_fix = get_option( 'tvc_auto_feed_fix', 'false' );
|
62 |
+
$third_party_attributes = get_option( 'tvc_third_party_attribute_keywords', '%wpmr%,%cpf%,%unit%,%bto%,%yoast%' );
|
63 |
+
$disabled_background_mode = get_option( 'tvc_disabled_background_mode', 'false' ); // @since 2.0.7
|
64 |
+
$process_logger_option = get_option( 'tvc_process_logger_status', 'false' ); // @since 2.9.0
|
65 |
+
$show_pi_option = get_option( 'tvc_show_product_identifiers', 'false' ); // @since 2.10.0
|
66 |
+
$sep_string = '# backup string for database ->';
|
67 |
+
$time_stamp = current_time( 'timestamp' );
|
68 |
+
|
69 |
+
$table_content = "$time_stamp#$db_version#$ftp_passive#$auto_fix#$third_party_attributes#$disabled_background_mode#$process_logger_option#$show_pi_option";
|
70 |
+
$table_content .= "$sep_string $main_table # <- # $main_table_content ";
|
71 |
+
$table_content .= "$sep_string $meta_table # <- # $meta_table_content ";
|
72 |
+
$table_content .= "$sep_string $channel_table # <- # $channel_table_content";
|
73 |
+
|
74 |
+
return $table_content;
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Restores the data in the database tables
|
79 |
+
*
|
80 |
+
* @since 1.7.0
|
81 |
+
*
|
82 |
+
* @param array $table_queries
|
83 |
+
*
|
84 |
+
* @return boolean
|
85 |
+
*/
|
86 |
+
public function restore_backup_data( $table_queries ) {
|
87 |
+
// retrieve the initial data strings
|
88 |
+
$product_feed_table_data = explode( ' # ', $table_queries[0][1] );
|
89 |
+
$product_feedmeta_table_data = explode( ' # ', $table_queries[1][1] );
|
90 |
+
$channel_table_data = explode( ' # ', $table_queries[2][1] );
|
91 |
+
|
92 |
+
// table names
|
93 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
94 |
+
$meta_table = $this->_table_prefix . 'feedmanager_product_feedmeta';
|
95 |
+
$channel_table = $this->_table_prefix . 'feedmanager_channel';
|
96 |
+
|
97 |
+
// clear the current data
|
98 |
+
$this->_wpdb->query( "TRUNCATE TABLE $main_table" );
|
99 |
+
$this->_wpdb->query( "TRUNCATE TABLE $meta_table" );
|
100 |
+
$this->_wpdb->query( "TRUNCATE TABLE $channel_table" );
|
101 |
+
|
102 |
+
// get the columns
|
103 |
+
$product_feed_table_columns = explode( ', ', $product_feed_table_data[0] );
|
104 |
+
$product_feedmeta_table_columns = explode( ', ', $product_feedmeta_table_data[0] );
|
105 |
+
$channel_table_columns = explode( ', ', $channel_table_data[0] );
|
106 |
+
|
107 |
+
// get the data
|
108 |
+
$product_feed_table_queries = explode( PHP_EOL, $product_feed_table_data[1] );
|
109 |
+
$product_feedmeta_table_queries = explode( PHP_EOL, $product_feedmeta_table_data[1] );
|
110 |
+
$channel_table_queries = explode( PHP_EOL, $channel_table_data[1] );
|
111 |
+
|
112 |
+
// restore the feedmanager_product_feed table
|
113 |
+
foreach ( $product_feed_table_queries as $table_data ) {
|
114 |
+
$product_feed_data = explode( "\t", $table_data );
|
115 |
+
|
116 |
+
if ( count( $product_feed_table_columns ) === count( $product_feed_data ) ) {
|
117 |
+
$data = array();
|
118 |
+
|
119 |
+
for ( $i = 0; $i < count( $product_feed_data ); $i ++ ) {
|
120 |
+
$data[ $product_feed_table_columns[ $i ] ] = $product_feed_data[ $i ];
|
121 |
+
}
|
122 |
+
|
123 |
+
$this->_wpdb->replace( $main_table, $data );
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
// restore the feedmanager_product_feedmeta table
|
128 |
+
foreach ( $product_feedmeta_table_queries as $table_metadata ) {
|
129 |
+
$product_feed_metadata = explode( "\t", $table_metadata );
|
130 |
+
|
131 |
+
if ( count( $product_feedmeta_table_columns ) === count( $product_feed_metadata ) ) {
|
132 |
+
$data = array();
|
133 |
+
|
134 |
+
for ( $i = 0; $i < count( $product_feed_metadata ); $i ++ ) {
|
135 |
+
$data[ $product_feedmeta_table_columns[ $i ] ] = $product_feed_metadata[ $i ];
|
136 |
+
}
|
137 |
+
|
138 |
+
$this->_wpdb->replace( $meta_table, $data );
|
139 |
+
}
|
140 |
+
}
|
141 |
+
|
142 |
+
// restore the feedmanager_channel table
|
143 |
+
foreach ( $channel_table_queries as $table_channeldata ) {
|
144 |
+
$channel_data = explode( "\t", $table_channeldata );
|
145 |
+
|
146 |
+
if ( count( $channel_table_columns ) === count( $channel_data ) ) {
|
147 |
+
$data = array();
|
148 |
+
|
149 |
+
for ( $i = 0; $i < count( $channel_data ); $i ++ ) {
|
150 |
+
$data[ $channel_table_columns[ $i ] ] = $channel_data[ $i ];
|
151 |
+
}
|
152 |
+
|
153 |
+
$this->_wpdb->replace( $channel_table, $data );
|
154 |
+
}
|
155 |
+
}
|
156 |
+
|
157 |
+
return true;
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Returns a tab separated string with the query results.
|
162 |
+
*
|
163 |
+
* @param (string) $query_result
|
164 |
+
* @param {array} $columns
|
165 |
+
*
|
166 |
+
* @return (string) backup string
|
167 |
+
*/
|
168 |
+
private function make_table_backup_string( $query_result, $columns ) {
|
169 |
+
$string = implode( $columns, ', ' ) . ' # ';
|
170 |
+
|
171 |
+
foreach ( $query_result as $row ) {
|
172 |
+
$string .= implode( "\t", $row ) . "\r\n";
|
173 |
+
}
|
174 |
+
|
175 |
+
return $string;
|
176 |
+
}
|
177 |
+
}
|
178 |
+
|
179 |
+
// end of TVC_Backup class
|
180 |
+
|
181 |
+
endif;
|
includes/data/class-tvc-channel-ftp.php
ADDED
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Product Feed Manager Channel FTP Class.
|
5 |
+
*
|
6 |
+
* @package TVC Product Feed Manager/Data/Classes
|
7 |
+
* @version 2.2.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
|
15 |
+
if ( ! class_exists( 'TVC_Channel_FTP' ) ) :
|
16 |
+
|
17 |
+
/**
|
18 |
+
* Channel FTP Class
|
19 |
+
*/
|
20 |
+
class TVC_Channel_FTP {
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Gets the correct channel zip file from the wp server
|
24 |
+
*
|
25 |
+
* @since 1.9.3 - switched from ftp to cURL procedures
|
26 |
+
*
|
27 |
+
* @param string $channel
|
28 |
+
* @param string $code
|
29 |
+
*
|
30 |
+
* @return boolean
|
31 |
+
*/
|
32 |
+
|
33 |
+
}
|
34 |
+
|
35 |
+
// end of TVC_Channel_FTP class
|
36 |
+
|
37 |
+
endif;
|
includes/data/class-tvc-channel.php
ADDED
@@ -0,0 +1,342 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Channels Class.
|
5 |
+
*
|
6 |
+
* @package TVC Product Feed Manager/Data/Classes
|
7 |
+
* @version 1.6.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Channel' ) ) :
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Channel Class
|
18 |
+
*/
|
19 |
+
class TVC_Channel {
|
20 |
+
/**
|
21 |
+
* Placeholder for the Channel Classes
|
22 |
+
*
|
23 |
+
* @var string
|
24 |
+
*/
|
25 |
+
private $_channels;
|
26 |
+
|
27 |
+
public function __construct() {
|
28 |
+
// TVC_CHANNEL_RELATED
|
29 |
+
$this->_channels = array(
|
30 |
+
new Channel( '0', 'usersetup', 'Free User Setup' ),
|
31 |
+
new Channel( '1', 'google', 'Google Merchant Centre' ),
|
32 |
+
new Channel( '2', 'bing', 'Bing Merchant Centre' ),
|
33 |
+
new Channel( '3', 'beslis', 'Beslis.nl' ),
|
34 |
+
new Channel( '4', 'pricegrabber', 'PriceGrabber' ),
|
35 |
+
new Channel( '5', 'shopping', 'Shopping.com (eBay)' ),
|
36 |
+
new Channel( '6', 'amazon', 'Amazon product ads' ),
|
37 |
+
new Channel( '7', 'connexity', 'Connexity' ),
|
38 |
+
new Channel( '8', 'become', 'Become' ),
|
39 |
+
// Become has been taken over by Connexity, https://merchants.become.com/DataFeedSpecification.html links to Connexity
|
40 |
+
new Channel( '9', 'nextag', 'Nextag' ),
|
41 |
+
new Channel( '10', 'kieskeurig', 'Kieskeurig.nl' ),
|
42 |
+
new Channel( '11', 'vergelijk', 'Vergelijk.nl' ),
|
43 |
+
new Channel( '12', 'koopjespakker', 'Koopjespakker.nl' ),
|
44 |
+
new Channel( '13', 'avantlink', 'AvantLink' ),
|
45 |
+
new Channel( '14', 'zbozi', 'Zbozi' ),
|
46 |
+
new Channel( '15', 'comcon', 'Commerce Connector' ),
|
47 |
+
new Channel( '16', 'facebook', 'Facebook' ),
|
48 |
+
new Channel( '17', 'bol', 'Bol.com' ),
|
49 |
+
new Channel( '18', 'adtraction', 'Adtraction' ),
|
50 |
+
new Channel( '19', 'ricardo', 'Ricardo.ch' ),
|
51 |
+
new Channel( '20', 'ebay', 'eBay' ),
|
52 |
+
new Channel( '21', 'shopzilla', 'Shopzilla' ),
|
53 |
+
new Channel( '22', 'converto', 'Converto' ),
|
54 |
+
new Channel( '23', 'idealo', 'Idealo' ),
|
55 |
+
new Channel( '24', 'heureka', 'Heureka' ),
|
56 |
+
new Channel( '25', 'pepperjam', 'Pepperjam' ),
|
57 |
+
new Channel( '26', 'galaxus_data', 'Galaxus Product Data' ),
|
58 |
+
new Channel( '27', 'galaxus_properties', 'Galaxus Product Properties' ),
|
59 |
+
new Channel( '28', 'galaxus_stock_pricing', 'Galaxus Product Stock Pricing' ),
|
60 |
+
new Channel( '996', '_tsv', 'Custom TSV Export' ),
|
61 |
+
new Channel( '997', '_txt', 'Custom TXT Export' ),
|
62 |
+
new Channel( '998', '_csv', 'Custom CSV Export' ),
|
63 |
+
new Channel( '999', '', 'Custom XML Export' ),
|
64 |
+
);
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Returns channel data from a specific channel
|
69 |
+
*
|
70 |
+
* @param string $channel_name channel name
|
71 |
+
*
|
72 |
+
* @return string Channel class
|
73 |
+
*/
|
74 |
+
public function get_active_channel_details( $channel_name ) {
|
75 |
+
foreach ( $this->_channels as $channel ) {
|
76 |
+
if ( $channel->channel_short === $channel_name ) {
|
77 |
+
return $channel;
|
78 |
+
}
|
79 |
+
}
|
80 |
+
return false;
|
81 |
+
}
|
82 |
+
|
83 |
+
public function get_channel_short_name( $channel_id ) {
|
84 |
+
foreach ( $this->_channels as $channel ) {
|
85 |
+
if ( $channel->channel_id === $channel_id ) {
|
86 |
+
return $channel->channel_short;
|
87 |
+
}
|
88 |
+
}
|
89 |
+
return false;
|
90 |
+
}
|
91 |
+
|
92 |
+
public function get_channel_name( $channel_id ) {
|
93 |
+
foreach ( $this->_channels as $channel ) {
|
94 |
+
if ( $channel->channel_id === $channel_id ) {
|
95 |
+
return $channel->channel_name;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
return false;
|
99 |
+
}
|
100 |
+
|
101 |
+
public function get_installed_channel_names() {
|
102 |
+
$file_class = new TVC_File();
|
103 |
+
|
104 |
+
return $file_class->get_installed_channels_from_file();
|
105 |
+
}
|
106 |
+
|
107 |
+
public function remove_channel( $channel, $nonce ) {
|
108 |
+
if ( wp_verify_nonce( $nonce, 'delete-channel-nonce' ) ) {
|
109 |
+
$this->remove_channel_source( $channel );
|
110 |
+
}
|
111 |
+
}
|
112 |
+
|
113 |
+
public function update_channel( $channel, $code, $nonce ) {
|
114 |
+
if ( wp_verify_nonce( $nonce, 'update-channel-nonce' ) ) {
|
115 |
+
$this->update_channel_source( $channel, $code );
|
116 |
+
} else {
|
117 |
+
tvc_write_log_file( sprintf( 'Failed to update channel %s because then nonce was not accepted. Given nonce = %s', $channel, $nonce ) );
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
121 |
+
public function install_channel( $channel, $code, $nonce ) {
|
122 |
+
if ( wp_verify_nonce( $nonce, 'install-channel-nonce' ) ) {
|
123 |
+
$this->install_channel_source( $channel, $code );
|
124 |
+
} else {
|
125 |
+
tvc_write_log_file( sprintf( 'Failed to install channel %s because then nonce was not accepted. Given nonce = %s', $channel, $nonce ) );
|
126 |
+
}
|
127 |
+
}
|
128 |
+
|
129 |
+
public function get_channels_from_server() {
|
130 |
+
$response = "Google Merchant Centre";
|
131 |
+
return $response;
|
132 |
+
}
|
133 |
+
|
134 |
+
public function get_number_of_updates_from_server( $channel_updated ) {
|
135 |
+
if ( date( 'Ymd' ) === get_option( 'tvc_channel_update_check_date' ) ) {
|
136 |
+
if ( $channel_updated ) {
|
137 |
+
tvc_decrease_update_ready_channels();
|
138 |
+
}
|
139 |
+
|
140 |
+
return get_option( 'tvc_channels_to_update' );
|
141 |
+
} else {
|
142 |
+
$response = $this->get_channels_from_server();
|
143 |
+
|
144 |
+
if ( ! is_wp_error( $response ) ) {
|
145 |
+
$available_channels = json_decode( $response['body'] );
|
146 |
+
|
147 |
+
if ( $available_channels ) {
|
148 |
+
$installed_channels_names = $this->get_installed_channel_names();
|
149 |
+
|
150 |
+
$this->add_status_data_to_available_channels( $available_channels, $installed_channels_names, false );
|
151 |
+
|
152 |
+
$stored_count = $this->count_updatable_channels( $available_channels );
|
153 |
+
|
154 |
+
$count = $channel_updated ? ( $stored_count - 1 ) : $stored_count;
|
155 |
+
update_option( 'tvc_channels_to_update', $count > 0 ? $count : 0 );
|
156 |
+
update_option( 'tvc_channel_update_check_date', date( 'Ymd' ) );
|
157 |
+
|
158 |
+
return $count;
|
159 |
+
}
|
160 |
+
} else {
|
161 |
+
echo tvc_handle_wp_errors_response(
|
162 |
+
$response,
|
163 |
+
sprintf(
|
164 |
+
/* translators: %s: url to the support page */
|
165 |
+
esc_html__(
|
166 |
+
'2141 - Please open a support ticket at %s for support on this issue.',
|
167 |
+
'tvc-product-feed-manager'
|
168 |
+
),
|
169 |
+
TVC_SUPPORT_PAGE_URL
|
170 |
+
)
|
171 |
+
);
|
172 |
+
|
173 |
+
return false;
|
174 |
+
}
|
175 |
+
}
|
176 |
+
|
177 |
+
return 0;
|
178 |
+
}
|
179 |
+
|
180 |
+
public function add_status_data_to_available_channels( &$available_channels, $installed_channels, $updated ) {
|
181 |
+
for ( $i = 0; $i < count( $available_channels ); $i ++ ) {
|
182 |
+
if ( in_array( $available_channels[ $i ]->short_name, $installed_channels ) ) {
|
183 |
+
$available_channels[ $i ]->status = 'installed';
|
184 |
+
|
185 |
+
$available_channels[ $i ]->installed_version = $available_channels[ $i ]->short_name === $updated ? $available_channels[ $i ]->version
|
186 |
+
: $this->get_channel_file_version( $available_channels[ $i ]->short_name, 0 );
|
187 |
+
} else {
|
188 |
+
$available_channels[ $i ]->status = 'not installed';
|
189 |
+
$available_channels[ $i ]->installed_version = '0';
|
190 |
+
}
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
private function get_channel_file_version( $channel_name, $rerun_counter ) {
|
195 |
+
if ( $rerun_counter < 3 ) {
|
196 |
+
if ( class_exists( 'TVC_' . ucfirst( $channel_name ) . '_Feed_Class' ) ) {
|
197 |
+
$class_var = 'TVC_' . ucfirst( $channel_name ) . '_Feed_Class';
|
198 |
+
|
199 |
+
$channel_class = new $class_var();
|
200 |
+
|
201 |
+
return $channel_class->get_version();
|
202 |
+
} else {
|
203 |
+
// reset the registered channels in the channel table
|
204 |
+
$db_class = new TVC_Database_Management();
|
205 |
+
$db_class->reset_channel_registration();
|
206 |
+
|
207 |
+
include_channels(); // include the channel classes
|
208 |
+
|
209 |
+
$rerun_counter ++;
|
210 |
+
|
211 |
+
return $this->get_channel_file_version( $channel_name, $rerun_counter );
|
212 |
+
}
|
213 |
+
} else {
|
214 |
+
if ( tvc_on_any_own_plugin_page() ) {
|
215 |
+
/* translators: %s: Name of a channel */
|
216 |
+
echo tvc_show_wp_error( sprintf( esc_html__( 'Channel %s is not installed correctly. Please try to Deactivate and then Activate the Feed Manager Plugin in your Plugins page.', 'tvc-product-feed-manager' ), $channel_name ) );
|
217 |
+
tvc_write_log_file( sprintf( 'Error: Channel %s is not installed correctly.', $channel_name ) );
|
218 |
+
}
|
219 |
+
|
220 |
+
return 'unknown';
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
private function count_updatable_channels( $channel_data ) {
|
225 |
+
$counter = 0;
|
226 |
+
|
227 |
+
foreach ( $channel_data as $channel ) {
|
228 |
+
if ( 'installed' === $channel->status && ( $channel->version > $channel->installed_version ) ) {
|
229 |
+
$counter ++;
|
230 |
+
}
|
231 |
+
}
|
232 |
+
|
233 |
+
return $counter;
|
234 |
+
}
|
235 |
+
|
236 |
+
private function update_channel_source( $channel, $code ) {
|
237 |
+
$file_class = new TVC_File();
|
238 |
+
$ftp_class = new TVC_Channel_FTP();
|
239 |
+
|
240 |
+
// remove the out dated channel source files from the server
|
241 |
+
$file_class->delete_channel_source_files( $channel );
|
242 |
+
|
243 |
+
$get_result = $ftp_class->get_channel_source_files( $channel, $code );
|
244 |
+
|
245 |
+
// get the update files from .com
|
246 |
+
if ( false !== $get_result ) {
|
247 |
+
// unzip the file
|
248 |
+
$file_class->unzip_channel_file( $channel );
|
249 |
+
|
250 |
+
// register the update
|
251 |
+
tvc_decrease_update_ready_channels();
|
252 |
+
}
|
253 |
+
}
|
254 |
+
|
255 |
+
private function remove_channel_source( $channel_short ) {
|
256 |
+
$data_class = new TVC_Data();
|
257 |
+
$file_class = new TVC_File();
|
258 |
+
|
259 |
+
// get the channel id that needs to be removed
|
260 |
+
$channel_id = $data_class->get_channel_id_from_short_name( $channel_short );
|
261 |
+
|
262 |
+
// unregister the channel
|
263 |
+
wp_dequeue_script( 'tvc_' . $channel_short . '-source-script' );
|
264 |
+
|
265 |
+
if ( $channel_id ) {
|
266 |
+
// remove channel related feed files
|
267 |
+
$file_class->delete_channel_feed_files( $channel_id );
|
268 |
+
|
269 |
+
// remove any channel related feed data and feed meta
|
270 |
+
$data_class->delete_channel_feeds( $channel_id );
|
271 |
+
}
|
272 |
+
|
273 |
+
// remove the channel from the feedmanager_channel table
|
274 |
+
$data_class->delete_channel( $channel_short );
|
275 |
+
|
276 |
+
// remove the channel source files from the server
|
277 |
+
$file_class->delete_channel_source_files( $channel_short );
|
278 |
+
}
|
279 |
+
|
280 |
+
private function install_channel_source( $channel_name, $code ) {
|
281 |
+
$ftp_class = new TVC_Channel_FTP();
|
282 |
+
$file_class = new TVC_File();
|
283 |
+
$data_class = new TVC_Data();
|
284 |
+
|
285 |
+
if ( plugin_version_supports_channel( $channel_name ) ) {
|
286 |
+
$get_result = $ftp_class->get_channel_source_files( $channel_name, $code );
|
287 |
+
|
288 |
+
// get the update files from .com
|
289 |
+
if ( false !== $get_result ) {
|
290 |
+
|
291 |
+
// unzip the file
|
292 |
+
$file_class->unzip_channel_file( $channel_name );
|
293 |
+
|
294 |
+
// register the new channel
|
295 |
+
$channel_details = $this->get_active_channel_details( $channel_name );
|
296 |
+
|
297 |
+
if ( false !== $channel_details ) {
|
298 |
+
$data_class->register_channel( $channel_name, $channel_details );
|
299 |
+
} else {
|
300 |
+
tvc_write_log_file( sprintf( 'Unable to register channel %s' . $channel_name ) );
|
301 |
+
}
|
302 |
+
} else {
|
303 |
+
tvc_write_log_file(
|
304 |
+
sprintf(
|
305 |
+
'Could not get the %s channel file from the server. Get_result message is %s.',
|
306 |
+
$channel_name,
|
307 |
+
$get_result
|
308 |
+
)
|
309 |
+
);
|
310 |
+
}
|
311 |
+
} else {
|
312 |
+
echo tvc_show_wp_warning(
|
313 |
+
sprintf(
|
314 |
+
/* translators: %s: Name of the selected channel */
|
315 |
+
esc_html__(
|
316 |
+
'Channel %s is not supported by your current plugin version. Please update your plugin to the latest version and try uploading this channel again.',
|
317 |
+
'tvc-product-feed-manager'
|
318 |
+
),
|
319 |
+
$channel_name
|
320 |
+
),
|
321 |
+
'tvc-product-feed-manager'
|
322 |
+
);
|
323 |
+
}
|
324 |
+
}
|
325 |
+
}
|
326 |
+
|
327 |
+
// end of TVC_Channel class
|
328 |
+
|
329 |
+
class Channel {
|
330 |
+
public $channel_id;
|
331 |
+
public $channel_short;
|
332 |
+
public $channel_name;
|
333 |
+
|
334 |
+
public function __construct( $id, $short, $name ) {
|
335 |
+
$this->channel_id = $id;
|
336 |
+
$this->channel_short = $short;
|
337 |
+
$this->channel_name = $name;
|
338 |
+
}
|
339 |
+
}
|
340 |
+
|
341 |
+
// end of Channel class
|
342 |
+
endif;
|
includes/data/class-tvc-data.php
ADDED
@@ -0,0 +1,713 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* WP Data Class.
|
5 |
+
*
|
6 |
+
* @package WP Product Feed Manager/Data/Classes
|
7 |
+
* @version 3.5.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Data' ) ) :
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Data Class
|
18 |
+
*/
|
19 |
+
class TVC_Data {
|
20 |
+
|
21 |
+
private $_queries_class;
|
22 |
+
private $_files_class;
|
23 |
+
|
24 |
+
public function __construct() {
|
25 |
+
$this->_queries_class = new TVC_Queries();
|
26 |
+
$this->_files_class = new TVC_File();
|
27 |
+
}
|
28 |
+
|
29 |
+
public function get_countries() {
|
30 |
+
return $this->_queries_class->read_countries();
|
31 |
+
}
|
32 |
+
|
33 |
+
/**
|
34 |
+
* @param $channel_short_name
|
35 |
+
* @return string|null
|
36 |
+
*/
|
37 |
+
public function get_channel_id_from_short_name( $channel_short_name ) {
|
38 |
+
return $this->_queries_class->get_channel_id( $channel_short_name );
|
39 |
+
}
|
40 |
+
|
41 |
+
public function get_channels() {
|
42 |
+
return $this->_queries_class->read_channels();
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @param $channel_short
|
47 |
+
* @return bool|false|int
|
48 |
+
*/
|
49 |
+
public function delete_channel( $channel_short ) {
|
50 |
+
$result = $this->_queries_class->remove_channel_from_db( $channel_short );
|
51 |
+
|
52 |
+
if ( ! $result || 0 == $result ) {
|
53 |
+
$result = $this->_queries_class->clean_channel_table();
|
54 |
+
}
|
55 |
+
|
56 |
+
return $result;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @param $channel_id
|
61 |
+
*/
|
62 |
+
public function delete_channel_feeds( $channel_id ) {
|
63 |
+
$feeds = $this->_queries_class->get_feeds_from_specific_channel( $channel_id );
|
64 |
+
|
65 |
+
foreach ( $feeds as $feed_id ) {
|
66 |
+
$this->_queries_class->delete_meta( $feed_id['product_feed_id'] );
|
67 |
+
$this->_queries_class->delete_feed( $feed_id['product_feed_id'] );
|
68 |
+
}
|
69 |
+
}
|
70 |
+
|
71 |
+
public function get_sources() {
|
72 |
+
return $this->_queries_class->read_sources();
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* @param $country_code
|
77 |
+
* @return array|object|stdClass|void|null
|
78 |
+
*/
|
79 |
+
public function get_country_id_from_short_code( $country_code ) {
|
80 |
+
if ( '0' !== $country_code && 0 !== $country_code ) {
|
81 |
+
return $this->_queries_class->get_country_id( $country_code );
|
82 |
+
} else {
|
83 |
+
$id = new stdClass();
|
84 |
+
$id->country_id = '233';
|
85 |
+
|
86 |
+
return $id;
|
87 |
+
}
|
88 |
+
}
|
89 |
+
|
90 |
+
public function get_schedule_data() {
|
91 |
+
return $this->_queries_class->read_active_schedule_data();
|
92 |
+
}
|
93 |
+
|
94 |
+
public function get_failed_feeds() {
|
95 |
+
return $this->_queries_class->read_failed_feeds();
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* @param $feed_id
|
100 |
+
* @return mixed
|
101 |
+
*/
|
102 |
+
public function get_feed_status( $feed_id ) {
|
103 |
+
$feed_status = $this->_queries_class->get_current_feed_status( $feed_id );
|
104 |
+
|
105 |
+
return $feed_status[0]->status_id;
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* @param $feed_id
|
110 |
+
* @param $nr
|
111 |
+
* @return false|int
|
112 |
+
*/
|
113 |
+
public function set_nr_of_feed_products( $feed_id, $nr ) {
|
114 |
+
return $this->_queries_class->set_nr_feed_products( $feed_id, $nr );
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* @param $feed_id
|
119 |
+
* @return array|object|void|null
|
120 |
+
*/
|
121 |
+
public function get_nr_of_feed_products( $feed_id ) {
|
122 |
+
return $this->_queries_class->get_nr_feed_products( $feed_id );
|
123 |
+
}
|
124 |
+
|
125 |
+
/**
|
126 |
+
* @param $feed_id
|
127 |
+
* @param $feed_url
|
128 |
+
* @param $nr_products
|
129 |
+
* @return false|int
|
130 |
+
*/
|
131 |
+
public function update_feed_data( $feed_id, $feed_url, $nr_products ) {
|
132 |
+
return $this->_queries_class->update_feed_update_data( $feed_id, $feed_url, $nr_products );
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Sets the status id of a feed
|
137 |
+
*
|
138 |
+
* 0 = unknown
|
139 |
+
* 1 = OK (will be updated automatically)
|
140 |
+
* 2 = On hold (will not be updated automatically)
|
141 |
+
* 3 = Processing
|
142 |
+
* 4 = In processing queue
|
143 |
+
* 5 = Has errors
|
144 |
+
* 6 = Failed processing
|
145 |
+
*
|
146 |
+
* @param string $feed_id
|
147 |
+
* @param int $status
|
148 |
+
*
|
149 |
+
* @return bool True if the update succeeded.
|
150 |
+
*/
|
151 |
+
public function update_feed_status( $feed_id, $status ) {
|
152 |
+
|
153 |
+
$message_level = 'MESSAGE';
|
154 |
+
|
155 |
+
switch ( $status ) {
|
156 |
+
case 1:
|
157 |
+
$message = sprintf( 'The feed status of feed %s has been set to OK (1)', $feed_id );
|
158 |
+
break;
|
159 |
+
|
160 |
+
case 2:
|
161 |
+
$message = sprintf( 'The feed status of feed %s has been set to On Hold (2)', $feed_id );
|
162 |
+
break;
|
163 |
+
|
164 |
+
case 3:
|
165 |
+
$message = sprintf( 'The feed status of feed %s has been set to Processing (3)', $feed_id );
|
166 |
+
break;
|
167 |
+
|
168 |
+
case 4:
|
169 |
+
$message = sprintf( 'The feed status of feed %s has been set to In processing queue (4)', $feed_id );
|
170 |
+
break;
|
171 |
+
|
172 |
+
case 5:
|
173 |
+
$message = sprintf( 'The feed status of feed %s has been set to Has errors (5)', $feed_id );
|
174 |
+
$message_level = 'ERROR';
|
175 |
+
break;
|
176 |
+
|
177 |
+
case 6:
|
178 |
+
$message = sprintf( 'The feed status of feed %s has been set to Failed processing (6)', $feed_id );
|
179 |
+
$message_level = 'ERROR';
|
180 |
+
break;
|
181 |
+
|
182 |
+
default:
|
183 |
+
$message = sprintf( 'Tried to update the status of feed %s but the status is unknown!', $feed_id );
|
184 |
+
$message_level = 'ERROR';
|
185 |
+
}
|
186 |
+
|
187 |
+
do_action( 'tvc_feed_generation_message', $feed_id, $message, $message_level );
|
188 |
+
|
189 |
+
return $this->_queries_class->update_feed_file_status( $feed_id, $status );
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Fills output fields with stored meta data
|
194 |
+
*
|
195 |
+
* @access public
|
196 |
+
*
|
197 |
+
* @param string $feed_id
|
198 |
+
* @param array $outputs
|
199 |
+
*
|
200 |
+
* @return array
|
201 |
+
*/
|
202 |
+
public function fill_output_fields_with_metadata( $feed_id, $outputs ) {
|
203 |
+
// read the meta data from the database
|
204 |
+
$metadata = $this->_queries_class->read_metadata( $feed_id );
|
205 |
+
|
206 |
+
// loop through the output rows
|
207 |
+
for ( $i = 0; $i < count( $outputs ); $i ++ ) {
|
208 |
+
// check if there is specific meta data for this output row
|
209 |
+
if ( count( $metadata ) > 0 ) {
|
210 |
+
foreach ( $metadata as $meta ) {
|
211 |
+
// look for a match
|
212 |
+
if ( $meta['meta_key'] === $outputs[ $i ]->field_label ) {
|
213 |
+
// put the meta data in the value variable of the output row
|
214 |
+
$outputs[ $i ]->value = $meta['meta_value'];
|
215 |
+
break; // break is required to stop the foreach loop and prevent the following loop from clearing the value
|
216 |
+
} else {
|
217 |
+
// as long as there is no match, leave the value empty
|
218 |
+
$outputs[ $i ]->value = '';
|
219 |
+
}
|
220 |
+
}
|
221 |
+
} else {
|
222 |
+
$outputs[ $i ]->value = '';
|
223 |
+
}
|
224 |
+
}
|
225 |
+
|
226 |
+
return $outputs;
|
227 |
+
}
|
228 |
+
|
229 |
+
/**
|
230 |
+
* Collects the source fields from all the different attributes.
|
231 |
+
*
|
232 |
+
* @param string $source_id The source id (not in use at the moment). Default 1.
|
233 |
+
*
|
234 |
+
* @return mixed|void|null
|
235 |
+
*/
|
236 |
+
public function get_source_fields( $source_id = '1' ) {
|
237 |
+
$source_fields = null;
|
238 |
+
|
239 |
+
switch ( $source_id ) {
|
240 |
+
case '1':
|
241 |
+
$data_class = new TVC_Data();
|
242 |
+
|
243 |
+
$custom_product_attributes = $this->_queries_class->get_custom_product_attributes();
|
244 |
+
$custom_product_fields = $this->_queries_class->get_custom_product_fields();
|
245 |
+
$product_attributes = $this->_queries_class->get_all_product_attributes();
|
246 |
+
$product_taxonomies = get_taxonomies();
|
247 |
+
$third_party_custom_fields = $data_class->get_third_party_custom_fields();
|
248 |
+
|
249 |
+
$combined_source_fields = $this->combine_custom_attributes_and_feeds(
|
250 |
+
$custom_product_attributes,
|
251 |
+
$custom_product_fields,
|
252 |
+
$product_attributes,
|
253 |
+
$product_taxonomies,
|
254 |
+
$third_party_custom_fields
|
255 |
+
);
|
256 |
+
|
257 |
+
$source_fields = apply_filters( 'tvc_all_source_fields', $combined_source_fields );
|
258 |
+
break;
|
259 |
+
|
260 |
+
default:
|
261 |
+
if ( 'valid' === get_option( 'tvc_lic_status' ) ) { // error message for paid versions
|
262 |
+
echo '<div id="error">' . __(
|
263 |
+
'Could not add custom fields because I could not identify the channel.
|
264 |
+
If not already done add the correct channel in the Manage Channels page.
|
265 |
+
Also try to deactivate and then activate the plugin.',
|
266 |
+
'tvc-product-feed-manager'
|
267 |
+
) . '</div>';
|
268 |
+
|
269 |
+
tvc_write_log_file( sprintf( 'Could not define the channel in a valid Premium plugin version. Feed id = %s', $source_id ) );
|
270 |
+
} else { // error message for free version
|
271 |
+
echo '<div id="error">' . __(
|
272 |
+
'Could not identify the channel.
|
273 |
+
Try to deactivate and then activate the plugin.
|
274 |
+
If that does not work remove the plugin through the WordPress Plugins page and than reinstall and activate it again.',
|
275 |
+
'tvc-product-feed-manager'
|
276 |
+
) . '</div>';
|
277 |
+
|
278 |
+
tvc_write_log_file( sprintf( 'Could not define the channel in a free plugin version. Feed id = %s', $source_id ) );
|
279 |
+
}
|
280 |
+
break;
|
281 |
+
}
|
282 |
+
return $source_fields;
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Get the attribute data of a specific feed.
|
287 |
+
*
|
288 |
+
* @param string $feed_id The id of the feed from which the attribute data is needed.
|
289 |
+
* @param string $channel_id The id of the channel of the feed.
|
290 |
+
*
|
291 |
+
* @return array The attribute data.
|
292 |
+
*/
|
293 |
+
public function get_attribute_data( $feed_id, $channel_id ) {
|
294 |
+
$is_custom = function_exists( 'tvc_channel_is_custom_channel' ) ? tvc_channel_is_custom_channel( $channel_id ) : false;
|
295 |
+
$channel_name = trim( $this->_queries_class->get_channel_short_name_from_db( $channel_id ) );
|
296 |
+
|
297 |
+
if ( ! $is_custom ) {
|
298 |
+
// read the output fields
|
299 |
+
$attributes_data = $this->_files_class->get_output_fields_for_specific_channel( $channel_name );
|
300 |
+
|
301 |
+
// if the feed is a stored feed, look for meta data to add (a feed an id of -1 is a new feed that not yet has been saved)
|
302 |
+
if ( $feed_id >= 0 ) {
|
303 |
+
// add meta data to the feeds output fields
|
304 |
+
$attributes_data = $this->fill_output_fields_with_metadata( $feed_id, $attributes_data );
|
305 |
+
}
|
306 |
+
} else {
|
307 |
+
$attributes_data = $this->get_custom_fields_with_metadata( $feed_id );
|
308 |
+
}
|
309 |
+
return $attributes_data;
|
310 |
+
}
|
311 |
+
|
312 |
+
/**
|
313 |
+
* @param $feed_id
|
314 |
+
* @return array|bool|object|null
|
315 |
+
*/
|
316 |
+
public function get_filter_query( $feed_id ) {
|
317 |
+
return $this->_queries_class->get_product_filter_query( $feed_id );
|
318 |
+
}
|
319 |
+
|
320 |
+
/**
|
321 |
+
* @param $variation_id
|
322 |
+
* @return array
|
323 |
+
*/
|
324 |
+
public function get_own_variation_data( $variation_id ) {
|
325 |
+
return $this->_queries_class->get_own_variable_product_attributes( $variation_id );
|
326 |
+
}
|
327 |
+
|
328 |
+
/**
|
329 |
+
* @param $product_data
|
330 |
+
* @param $parent_id
|
331 |
+
* @param $post_columns_query_string
|
332 |
+
*/
|
333 |
+
public function add_parent_data( &$product_data, $parent_id, $post_columns_query_string ) {
|
334 |
+
$parent_product_data = (array) $this->_queries_class->read_post_data( $parent_id, $post_columns_query_string );
|
335 |
+
$sources_that_always_use_parent_data = apply_filters( 'sources_that_always_use_data_from_parent', array( 'post_excerpt' ) );
|
336 |
+
|
337 |
+
$columns = explode( ', ', $post_columns_query_string );
|
338 |
+
|
339 |
+
foreach ( $columns as $column ) {
|
340 |
+
if ( ( '' === $product_data[ $column ] && array_key_exists( $column, $parent_product_data ) && '' !== $parent_product_data[ $column ] )
|
341 |
+
|| in_array( $column, $sources_that_always_use_parent_data ) ) {
|
342 |
+
$product_data[ $column ] = $parent_product_data[ $column ];
|
343 |
+
}
|
344 |
+
}
|
345 |
+
}
|
346 |
+
|
347 |
+
/**
|
348 |
+
* @param $feed_id
|
349 |
+
* @return array
|
350 |
+
*/
|
351 |
+
public function get_custom_fields_with_metadata( $feed_id ) {
|
352 |
+
// read the meta data from the database
|
353 |
+
$metadata = $this->_queries_class->read_metadata( $feed_id );
|
354 |
+
$outputs = array();
|
355 |
+
|
356 |
+
// loop through the output rows
|
357 |
+
for ( $i = 0; $i < count( $metadata ); $i ++ ) {
|
358 |
+
$object = new stdClass();
|
359 |
+
|
360 |
+
$object->field_id = $i + 1;
|
361 |
+
$object->category_id = '5';
|
362 |
+
$object->field_label = $metadata[ $i ]['meta_key'];
|
363 |
+
$object->value = $metadata[ $i ]['meta_value'];
|
364 |
+
|
365 |
+
array_push( $outputs, $object );
|
366 |
+
}
|
367 |
+
|
368 |
+
return $outputs;
|
369 |
+
}
|
370 |
+
|
371 |
+
public function get_third_party_custom_fields() {
|
372 |
+
$custom_fields = array();
|
373 |
+
|
374 |
+
// YITH Brands plugin
|
375 |
+
$yith_brand_label = get_option( 'yith_wcbr_brands_label' );
|
376 |
+
if ( $yith_brand_label ) {
|
377 |
+
array_push( $custom_fields, $yith_brand_label );
|
378 |
+
}
|
379 |
+
|
380 |
+
// WooCommerce Brands
|
381 |
+
if ( in_array(
|
382 |
+
'woocommerce-brands/woocommerce-brands.php',
|
383 |
+
apply_filters(
|
384 |
+
'active_plugins',
|
385 |
+
get_option( 'active_plugins' )
|
386 |
+
)
|
387 |
+
) ) {
|
388 |
+
array_push( $custom_fields, 'Brand' );
|
389 |
+
}
|
390 |
+
|
391 |
+
return $custom_fields;
|
392 |
+
}
|
393 |
+
|
394 |
+
/**
|
395 |
+
* Checks if other feeds than the active feed are still on processing status. If so, set these feeds to error
|
396 |
+
*
|
397 |
+
* @param string $active_feed_id
|
398 |
+
*
|
399 |
+
* @since 1.10.0
|
400 |
+
*
|
401 |
+
*/
|
402 |
+
public function check_for_failed_feeds( $active_feed_id ) {
|
403 |
+
$processing_feeds = $this->_queries_class->get_feed_ids_with_specific_status( '3' );
|
404 |
+
$failed_feed_ids = '';
|
405 |
+
|
406 |
+
foreach ( $processing_feeds as $feed ) {
|
407 |
+
if ( $active_feed_id !== $feed->product_feed_id ) {
|
408 |
+
$this->update_feed_status( $feed->product_feed_id, 6 );
|
409 |
+
$failed_feed_ids .= ', ' . $feed->product_feed_id;
|
410 |
+
}
|
411 |
+
}
|
412 |
+
|
413 |
+
if ( $failed_feed_ids ) {
|
414 |
+
$message = sprintf( 'Starting the update of feed %s, the following feeds where still registered as being active: %s and are now set to the status FAIL.', $active_feed_id, $failed_feed_ids );
|
415 |
+
do_action( 'tvc_feed_generation_message', $active_feed_id, $message, 'ERROR' );
|
416 |
+
}
|
417 |
+
}
|
418 |
+
|
419 |
+
/**
|
420 |
+
* Converts feed data items that are send through an ajax call to the corresponding database names.
|
421 |
+
*
|
422 |
+
* @param $feed_data
|
423 |
+
*
|
424 |
+
* @return array
|
425 |
+
* @since 2.5.0
|
426 |
+
*
|
427 |
+
*/
|
428 |
+
public function convert_ajax_feed_data_to_database_format( $feed_data ) {
|
429 |
+
$result = array();
|
430 |
+
|
431 |
+
foreach ( $feed_data as $data_item ) {
|
432 |
+
if ( 'product_feed_id' !== $data_item->name ) {
|
433 |
+
|
434 |
+
if ( 'url' === $data_item->name ) {
|
435 |
+
$data_item->value = $this->verify_url( $data_item->value );
|
436 |
+
}
|
437 |
+
|
438 |
+
$result[ $data_item->name ] = $data_item->value;
|
439 |
+
}
|
440 |
+
}
|
441 |
+
|
442 |
+
return $result;
|
443 |
+
}
|
444 |
+
|
445 |
+
/**
|
446 |
+
* Gets the correct data types from the feed data and puts them into an array in the correct order.
|
447 |
+
*
|
448 |
+
* @param $feed_data
|
449 |
+
* @param $ajax_feed_data
|
450 |
+
*
|
451 |
+
* @return array
|
452 |
+
* @since 2.5.0
|
453 |
+
*
|
454 |
+
*/
|
455 |
+
public function get_types_from_feed_data( $feed_data, $ajax_feed_data ) {
|
456 |
+
$result = array();
|
457 |
+
|
458 |
+
foreach ( $feed_data as $data_key => $value ) {
|
459 |
+
$feed_item = array_filter(
|
460 |
+
$ajax_feed_data,
|
461 |
+
function ( $item ) use ( $data_key ) {
|
462 |
+
return $item->name == $data_key;
|
463 |
+
}
|
464 |
+
);
|
465 |
+
|
466 |
+
array_push( $result, reset( $feed_item )->type );
|
467 |
+
}
|
468 |
+
|
469 |
+
return $result;
|
470 |
+
}
|
471 |
+
|
472 |
+
/**
|
473 |
+
* @param $feed_id
|
474 |
+
* @return bool|stdClass
|
475 |
+
*/
|
476 |
+
public function get_feed_data( $feed_id ) {
|
477 |
+
// get the main data
|
478 |
+
$main_feed_data = $this->_queries_class->read_feed( $feed_id );
|
479 |
+
$main_data = $this->convert_data_to_feed_data( $main_feed_data[0] );
|
480 |
+
|
481 |
+
if ( false === $main_data ) {
|
482 |
+
return $main_data;
|
483 |
+
}
|
484 |
+
|
485 |
+
$main_data->attributes = array();
|
486 |
+
|
487 |
+
$channel = trim( $this->_queries_class->get_channel_short_name_from_db( $main_feed_data[0]['channel'] ) );
|
488 |
+
$is_custom = function_exists( 'tvc_channel_is_custom_channel' ) ? tvc_channel_is_custom_channel( $channel ) : false;
|
489 |
+
|
490 |
+
// read the output fields
|
491 |
+
if ( ! $is_custom ) {
|
492 |
+
$outputs = apply_filters( 'tvc_get_feed_attributes', $this->_files_class->get_output_fields_for_specific_channel( $channel ), $feed_id, $main_feed_data[0]['feed_type_id'] );
|
493 |
+
} else {
|
494 |
+
$outputs = $this->get_custom_fields_with_metadata( $feed_id );
|
495 |
+
}
|
496 |
+
|
497 |
+
// add meta data to the feeds output fields
|
498 |
+
$output_fields = $this->fill_output_fields_with_metadata( $feed_id, $outputs );
|
499 |
+
$inputs = $this->get_advised_inputs( $main_data->channel, $main_feed_data[0]['feed_type_id'] );
|
500 |
+
|
501 |
+
for ( $i = 0; $i < count( $output_fields ); $i ++ ) {
|
502 |
+
$output_title = $output_fields[ $i ]->field_label;
|
503 |
+
$is_active = false;
|
504 |
+
|
505 |
+
if ( $output_fields[ $i ]->category_id > 0 && $output_fields[ $i ]->category_id < 3 ) {
|
506 |
+
$is_active = true;
|
507 |
+
}
|
508 |
+
if ( ! empty( $output_fields[ $i ]->value ) && 'undefined' !== $output_fields[ $i ]->value ) {
|
509 |
+
$is_active = true;
|
510 |
+
}
|
511 |
+
|
512 |
+
$advised_source = property_exists( $inputs, $output_title ) ? $advised_source = $inputs->{$output_title} : '';
|
513 |
+
$this->add_attribute( $main_data->attributes, $i, $output_title, $advised_source, $output_fields[ $i ]->value, $output_fields[ $i ]->category_id, $is_active, 0, 0, 0 );
|
514 |
+
}
|
515 |
+
|
516 |
+
$this->set_output_attribute_levels( $main_data );
|
517 |
+
|
518 |
+
return $main_data;
|
519 |
+
}
|
520 |
+
|
521 |
+
/**
|
522 |
+
* @param $main_data
|
523 |
+
*/
|
524 |
+
// ALERT has a relation with the tvc_setOutputAttributeLevels() function in the logic.js file
|
525 |
+
private function set_output_attribute_levels( &$main_data ) {
|
526 |
+
$channel_base_class = new TVC_Channel();
|
527 |
+
$channel_short_name = $channel_base_class->get_channel_short_name( $main_data->channel );
|
528 |
+
|
529 |
+
if ( class_exists( 'TVC_' . ucfirst( $channel_short_name ) . '_Feed_Class' ) ) {
|
530 |
+
$class_name = 'TVC_' . ucfirst( $channel_short_name ) . '_Feed_Class';
|
531 |
+
$feed_class = new $class_name();
|
532 |
+
|
533 |
+
if ( method_exists( $feed_class, 'set_feed_output_attribute_levels' ) ) {
|
534 |
+
$feed_class->set_feed_output_attribute_levels( $main_data );
|
535 |
+
}
|
536 |
+
}
|
537 |
+
}
|
538 |
+
|
539 |
+
/**
|
540 |
+
* @param $attribute
|
541 |
+
* @param $id
|
542 |
+
* @param $title
|
543 |
+
* @param $advised_source
|
544 |
+
* @param $value
|
545 |
+
* @param $field_level
|
546 |
+
* @param $is_active
|
547 |
+
* @param $nr_queries
|
548 |
+
* @param $nr_value_edits
|
549 |
+
* @param $nr_value_conditions
|
550 |
+
*/
|
551 |
+
private function add_attribute(
|
552 |
+
&$attribute, $id, $title, $advised_source, $value, $field_level, $is_active,
|
553 |
+
$nr_queries, $nr_value_edits, $nr_value_conditions
|
554 |
+
) {
|
555 |
+
|
556 |
+
$attribute_object = new stdClass();
|
557 |
+
|
558 |
+
$attribute_object->rowId = $id;
|
559 |
+
$attribute_object->fieldName = $title;
|
560 |
+
$attribute_object->advisedSource = $advised_source;
|
561 |
+
$attribute_object->value = $value;
|
562 |
+
$attribute_object->fieldLevel = $field_level;
|
563 |
+
$attribute_object->isActive = $is_active;
|
564 |
+
$attribute_object->nrQueries = $nr_queries;
|
565 |
+
$attribute_object->nrValueEdits = $nr_value_edits;
|
566 |
+
$attribute_object->nrValueConditions = $nr_value_conditions;
|
567 |
+
|
568 |
+
array_push( $attribute, $attribute_object );
|
569 |
+
}
|
570 |
+
|
571 |
+
/**
|
572 |
+
* @param $data
|
573 |
+
* @return bool|stdClass
|
574 |
+
*/
|
575 |
+
private function convert_data_to_feed_data( $data ) {
|
576 |
+
|
577 |
+
if ( ! key_exists( 'product_feed_id', $data ) ) {
|
578 |
+
return false;
|
579 |
+
}
|
580 |
+
|
581 |
+
$feed = new stdClass();
|
582 |
+
|
583 |
+
$feed->feedId = $data['product_feed_id'];
|
584 |
+
$feed->title = $data['title'];
|
585 |
+
$feed->mainCategory = $data['main_category'];
|
586 |
+
$feed->categoryMapping = $data['category_mapping'];
|
587 |
+
$feed->isAggregator = $data['is_aggregator'];
|
588 |
+
$feed->includeVariations = $data['include_variations'];
|
589 |
+
$feed->feedTitle = $data['feed_title'] !== null ? $data['feed_title'] : '';
|
590 |
+
$feed->feedDescription = $data['feed_description'] !== null ? $data['feed_description'] : '';
|
591 |
+
$feed->url = $data['url'];
|
592 |
+
$feed->dataSource = $data['source'];
|
593 |
+
$feed->channel = $data['channel'];
|
594 |
+
$feed->country = $data['country'];
|
595 |
+
$feed->status = $data['status_id'];
|
596 |
+
$feed->baseStatusId = $data['base_status_id'];
|
597 |
+
$feed->feedTypeId = $data['feed_type_id'];
|
598 |
+
$feed->updateSchedule = $data['schedule'];
|
599 |
+
$feed->language = $data['language'] !== null ? $data['language'] : '';
|
600 |
+
|
601 |
+
return $feed;
|
602 |
+
}
|
603 |
+
|
604 |
+
/**
|
605 |
+
* @param $channel_id
|
606 |
+
* @param $feed_type_id
|
607 |
+
* @return mixed|void
|
608 |
+
*/
|
609 |
+
// TVC_CHANNEL_RELATED
|
610 |
+
private function get_advised_inputs( $channel_id, $feed_type_id ) {
|
611 |
+
$feed_class = new TVC_Google_Feed_Class();
|
612 |
+
// as long as only WooCommerce is supported, I can get away with only switching on a specific channel
|
613 |
+
$advised_inputs = $feed_class->woocommerce_to_feed_fields();
|
614 |
+
return apply_filters( 'tvc_advised_inputs', $advised_inputs, $feed_type_id );
|
615 |
+
}
|
616 |
+
|
617 |
+
/**
|
618 |
+
* Makes sure that the url is correct and has no forbidden characters before it's being stored in the database
|
619 |
+
*
|
620 |
+
* @param $url string complete url
|
621 |
+
*
|
622 |
+
* @return string verified url
|
623 |
+
*/
|
624 |
+
private function verify_url( $url ) {
|
625 |
+
$forbidden_name_chars = tvc_forbidden_file_name_characters();
|
626 |
+
$last_slash = strrpos( $url, '/' );
|
627 |
+
$url_string = substr( $url, 0, $last_slash + 1 );
|
628 |
+
$feed_name = substr( $url, $last_slash + 1 );
|
629 |
+
$correct_feed_name = str_replace( $forbidden_name_chars, '-', $feed_name );
|
630 |
+
return $url_string . $correct_feed_name;
|
631 |
+
}
|
632 |
+
|
633 |
+
/**
|
634 |
+
* @param $channel_short_name
|
635 |
+
* @param $channel_data
|
636 |
+
*/
|
637 |
+
public function register_channel( $channel_short_name, $channel_data ) {
|
638 |
+
if ( ! $this->_queries_class->get_channel_id( $channel_short_name ) ) { // make sure the channel is not yet registered
|
639 |
+
$this->_queries_class->register_a_channel( $channel_short_name, $channel_data->channel_id, $channel_data->channel_name );
|
640 |
+
}
|
641 |
+
}
|
642 |
+
|
643 |
+
/**
|
644 |
+
* @param $attributes
|
645 |
+
* @param $feeds
|
646 |
+
* @param $product_attributes
|
647 |
+
* @param $product_taxonomies
|
648 |
+
* @param $third_party_fields
|
649 |
+
* @return mixed
|
650 |
+
*/
|
651 |
+
private function combine_custom_attributes_and_feeds( $attributes, $feeds, $product_attributes, $product_taxonomies, $third_party_fields ) {
|
652 |
+
$prev_dup_array = array(); // used to prevent doubles
|
653 |
+
|
654 |
+
foreach ( $feeds as $feed ) {
|
655 |
+
$obj = new stdClass();
|
656 |
+
|
657 |
+
$obj->attribute_name = $feed;
|
658 |
+
$obj->attribute_label = $feed;
|
659 |
+
|
660 |
+
array_push( $attributes, $obj );
|
661 |
+
array_push( $prev_dup_array, $obj->attribute_label );
|
662 |
+
}
|
663 |
+
|
664 |
+
foreach ( $product_taxonomies as $taxonomy ) {
|
665 |
+
if ( ! in_array( $taxonomy, $prev_dup_array ) ) {
|
666 |
+
$obj = new stdClass();
|
667 |
+
$obj->attribute_name = $taxonomy;
|
668 |
+
$obj->attribute_label = $taxonomy;
|
669 |
+
|
670 |
+
array_push( $attributes, $obj );
|
671 |
+
array_push( $prev_dup_array, $taxonomy );
|
672 |
+
}
|
673 |
+
}
|
674 |
+
|
675 |
+
foreach ( $product_attributes as $attribute_string ) {
|
676 |
+
$attribute_object = maybe_unserialize( $attribute_string->meta_value );
|
677 |
+
|
678 |
+
if ( $attribute_object && ( is_object( $attribute_object ) || is_array( $attribute_object ) ) ) {
|
679 |
+
foreach ( $attribute_object as $attribute ) {
|
680 |
+
if ( ! in_array( $attribute['name'], $prev_dup_array ) ) {
|
681 |
+
$obj = new stdClass();
|
682 |
+
$obj->attribute_name = $attribute['name'];
|
683 |
+
$obj->attribute_label = $attribute['name'];
|
684 |
+
|
685 |
+
array_push( $attributes, $obj );
|
686 |
+
array_push( $prev_dup_array, $attribute['name'] );
|
687 |
+
}
|
688 |
+
}
|
689 |
+
} else {
|
690 |
+
if ( $attribute_object ) {
|
691 |
+
tvc_write_log_file( $attribute_object, 'debug' );
|
692 |
+
}
|
693 |
+
}
|
694 |
+
}
|
695 |
+
|
696 |
+
foreach ( $third_party_fields as $field_label ) {
|
697 |
+
if ( ! in_array( $field_label, $prev_dup_array ) ) {
|
698 |
+
$obj = new stdClass();
|
699 |
+
$obj->attribute_name = $field_label;
|
700 |
+
$obj->attribute_label = $field_label;
|
701 |
+
|
702 |
+
array_push( $attributes, $obj );
|
703 |
+
array_push( $prev_dup_array, $field_label );
|
704 |
+
}
|
705 |
+
}
|
706 |
+
return $attributes;
|
707 |
+
}
|
708 |
+
}
|
709 |
+
// end of TVC_Data_Class
|
710 |
+
|
711 |
+
endif;
|
712 |
+
|
713 |
+
$dataclass = new TVC_Data();
|
includes/data/class-tvc-db-management.php
ADDED
@@ -0,0 +1,325 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Db Management Class.
|
5 |
+
*
|
6 |
+
* @package TVC Product Feed Manager/Data/Classes
|
7 |
+
* @version 1.9.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Db_Management' ) ) :
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Db Management Class
|
18 |
+
*/
|
19 |
+
class TVC_Db_Management {
|
20 |
+
|
21 |
+
public static function table_exists( $table_name ) {
|
22 |
+
global $wpdb;
|
23 |
+
|
24 |
+
if ( $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->prefix . $table_name ) ) === $wpdb->prefix . $table_name ) {
|
25 |
+
return true;
|
26 |
+
} else {
|
27 |
+
return false;
|
28 |
+
}
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Makes a duplicate of a selected feed and stores it in the database.
|
33 |
+
*
|
34 |
+
* @param string $feed_id Feed id of the feed that needs to be duplicated.
|
35 |
+
*
|
36 |
+
* @return boolean False if duplication process failed.
|
37 |
+
*/
|
38 |
+
public static function duplicate_feed( $feed_id ) {
|
39 |
+
$queries_class = new TVC_Queries();
|
40 |
+
$support_class = new TVC_Feed_Support();
|
41 |
+
|
42 |
+
// Get the feed data.
|
43 |
+
$feed_data = $queries_class->get_feed_row( $feed_id );
|
44 |
+
|
45 |
+
// Get the meta data.
|
46 |
+
$meta_data = $queries_class->read_metadata( $feed_id );
|
47 |
+
|
48 |
+
// Get the Feed Filter data.
|
49 |
+
$feed_filter_data = $queries_class->get_product_filter_query( $feed_id );
|
50 |
+
|
51 |
+
// Get the category mapping.
|
52 |
+
$category_mapping = $queries_class->read_category_mapping( $feed_id );
|
53 |
+
|
54 |
+
// Generate a new unique feed name.
|
55 |
+
$feed_data->title = $support_class->next_unique_feed_name( $feed_data->title );
|
56 |
+
$feed_data->url = esc_html__( 'Feed needs to be generated first', 'tvc-product-feed-manager' );
|
57 |
+
|
58 |
+
$feed_data_to_store = array(
|
59 |
+
'channel_id' => $feed_data->channel_id,
|
60 |
+
'language' => $feed_data->language,
|
61 |
+
'is_aggregator' => $feed_data->is_aggregator,
|
62 |
+
'include_variations' => $feed_data->include_variations,
|
63 |
+
'country_id' => $feed_data->country_id,
|
64 |
+
'source_id' => $feed_data->source_id,
|
65 |
+
'title' => $feed_data->title,
|
66 |
+
'feed_title' => $feed_data->feed_title,
|
67 |
+
'feed_description' => $feed_data->feed_description,
|
68 |
+
'main_category' => $feed_data->main_category,
|
69 |
+
'url' => $feed_data->url,
|
70 |
+
'status_id' => $feed_data->status_id,
|
71 |
+
'schedule' => $feed_data->schedule,
|
72 |
+
'products' => 0,
|
73 |
+
'feed_type_id' => $feed_data->feed_type_id,
|
74 |
+
'aggregator_name' => $feed_data->aggregator_name,
|
75 |
+
'publisher_name' => $feed_data->publisher_name,
|
76 |
+
'publisher_favicon_url' => $feed_data->publisher_favicon_url,
|
77 |
+
);
|
78 |
+
|
79 |
+
$feed_data_types = array(
|
80 |
+
'%d',
|
81 |
+
'%s',
|
82 |
+
'%d',
|
83 |
+
'%d',
|
84 |
+
'%d',
|
85 |
+
'%d',
|
86 |
+
'%s',
|
87 |
+
'%s',
|
88 |
+
'%s',
|
89 |
+
'%s',
|
90 |
+
'%s',
|
91 |
+
'%d',
|
92 |
+
'%s',
|
93 |
+
'%d',
|
94 |
+
'%d',
|
95 |
+
'%s',
|
96 |
+
'%s',
|
97 |
+
'%s',
|
98 |
+
);
|
99 |
+
|
100 |
+
// Store a copy of the new feed in the database.
|
101 |
+
$new_feed_id = $queries_class->create_feed( $feed_data_to_store, $feed_data_types );
|
102 |
+
|
103 |
+
return $new_feed_id > 0 ? $queries_class->insert_meta_data( $new_feed_id, $meta_data, $feed_filter_data, $category_mapping ) : false;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Backups all plugin related data from the database to a file
|
108 |
+
*
|
109 |
+
* @since 1.7.2
|
110 |
+
*
|
111 |
+
* @param string $backup_file_name
|
112 |
+
*
|
113 |
+
* @return boolean
|
114 |
+
*/
|
115 |
+
public static function backup_database_tables( $backup_file_name ) {
|
116 |
+
$backup_class = new TVC_Backup();
|
117 |
+
$file_class = new TVC_File();
|
118 |
+
|
119 |
+
$backup_file = TVC_BACKUP_DIR . '/' . $backup_file_name . '.sql';
|
120 |
+
$backup_path = str_replace( '\\', '/', $backup_file );
|
121 |
+
|
122 |
+
// prepare the folder structure to support saving backup files
|
123 |
+
if ( ! file_exists( TVC_BACKUP_DIR ) ) {
|
124 |
+
TVC_Folders::make_backup_folder();
|
125 |
+
}
|
126 |
+
|
127 |
+
if ( ! file_exists( $backup_path ) ) {
|
128 |
+
$backup_file_text = $backup_class->read_full_backup_data();
|
129 |
+
|
130 |
+
return $file_class->write_full_backup_file( $backup_path, $backup_file_text );
|
131 |
+
} else {
|
132 |
+
echo tvc_show_wp_warning( esc_html__( 'A backup file with the selected name already exists. Please choose an other name or delete the existing file first.', 'tvc-product-feed-manager' ) );
|
133 |
+
|
134 |
+
return false;
|
135 |
+
}
|
136 |
+
}
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Checks the existing backup files for non compliant versions
|
140 |
+
*
|
141 |
+
* @since 1.8.0
|
142 |
+
*
|
143 |
+
* @return boolean true if a non compliant backup file exists
|
144 |
+
*/
|
145 |
+
public static function invalid_backup_exist() {
|
146 |
+
if ( ! file_exists( TVC_BACKUP_DIR ) ) {
|
147 |
+
return false;
|
148 |
+
}
|
149 |
+
|
150 |
+
$files = tvc_list_sql_files( TVC_BACKUP_DIR );
|
151 |
+
|
152 |
+
if ( count( $files ) === 0 ) {
|
153 |
+
return false;
|
154 |
+
}
|
155 |
+
|
156 |
+
foreach ( $files as $file ) {
|
157 |
+
$backup_string = file_get_contents( $file );
|
158 |
+
|
159 |
+
// get the db version
|
160 |
+
$backup_version_string = ltrim( substr( $backup_string, stripos( $backup_string, '#' ) ), '#' );
|
161 |
+
$backup_db_version = substr( $backup_version_string, 0, strpos( $backup_version_string, '#' ) );
|
162 |
+
|
163 |
+
if ( $backup_db_version < get_option( 'tvc_db_version' ) ) {
|
164 |
+
return true;
|
165 |
+
}
|
166 |
+
}
|
167 |
+
|
168 |
+
return false;
|
169 |
+
}
|
170 |
+
|
171 |
+
/**
|
172 |
+
* Restores the data from a backup file
|
173 |
+
*
|
174 |
+
* @since 1.7.2
|
175 |
+
*
|
176 |
+
* @param string name of the backup file
|
177 |
+
*
|
178 |
+
* @return boolean if restored successfully, string when not
|
179 |
+
*/
|
180 |
+
public static function restore_backup( $backup_file_name ) {
|
181 |
+
$backup_class = new TVC_Backup();
|
182 |
+
|
183 |
+
$backup_file = TVC_BACKUP_DIR . '/' . $backup_file_name;
|
184 |
+
$backup_path = str_replace( '\\', '/', $backup_file );
|
185 |
+
|
186 |
+
$current_db_version = get_option( 'tvc_db_version' );
|
187 |
+
|
188 |
+
if ( file_exists( $backup_path ) ) {
|
189 |
+
$table_queries = array();
|
190 |
+
$backup_string = file_get_contents( $backup_file );
|
191 |
+
|
192 |
+
// remove the date string
|
193 |
+
$backup_string = substr( $backup_string, stripos( $backup_string, '#' ) );
|
194 |
+
|
195 |
+
// get the db version
|
196 |
+
$backup_db_version = ltrim( $backup_string, '#' );
|
197 |
+
$backup_db_version = substr( $backup_db_version, 0, strpos( $backup_db_version, '#' ) );
|
198 |
+
|
199 |
+
if ( $backup_db_version < $current_db_version ) {
|
200 |
+
return esc_html__( 'The backup file is of an older version of the database and can not be restored as it is not compatible with the current database.', 'tvc-product-feed-manager' );
|
201 |
+
}
|
202 |
+
|
203 |
+
// remove the version
|
204 |
+
$backup_string = self::remove_left_data_part( $backup_string );
|
205 |
+
|
206 |
+
// remove the ftp passive setting
|
207 |
+
$backup_string = self::remove_left_data_part( $backup_string );
|
208 |
+
|
209 |
+
// reset the auto feed fix setting
|
210 |
+
$auto_feed_fix_setting = ltrim( $backup_string, '#' );
|
211 |
+
$auto_feed_fix_setting = substr( $auto_feed_fix_setting, 1, strpos( $auto_feed_fix_setting, '#' ) );
|
212 |
+
update_option( 'tvc_auto_feed_fix', $auto_feed_fix_setting );
|
213 |
+
|
214 |
+
// remove the auto feed fix setting
|
215 |
+
$backup_string = self::remove_left_data_part( $backup_string );
|
216 |
+
|
217 |
+
// reset the disable background option
|
218 |
+
$disable_background_setting = ltrim( $backup_string, '#' );
|
219 |
+
$disable_background_setting = substr( $disable_background_setting, 1, strpos( $disable_background_setting, '#' ) );
|
220 |
+
update_option( 'tvc_disabled_background_mode', $disable_background_setting );
|
221 |
+
|
222 |
+
// remove the disable background option string
|
223 |
+
$backup_string = self::remove_left_data_part( $backup_string );
|
224 |
+
|
225 |
+
// reset the show product identifiers option string
|
226 |
+
$show_product_identifiers_setting = ltrim( $backup_string, '#' );
|
227 |
+
$show_product_identifiers_setting = substr( $show_product_identifiers_setting, 1, strpos( $show_product_identifiers_setting, '#' ) );
|
228 |
+
update_option( 'tvc_show_product_identifiers', $show_product_identifiers_setting );
|
229 |
+
|
230 |
+
// remove the show product identifiers option string
|
231 |
+
$backup_string = self::remove_left_data_part( $backup_string );
|
232 |
+
|
233 |
+
// split the string in table specific rows
|
234 |
+
$table_strings = explode( '# backup string for database -> ', $backup_string );
|
235 |
+
|
236 |
+
foreach ( $table_strings as $string ) {
|
237 |
+
$table_name = substr( $string, 0, stripos( $string, '#' ) );
|
238 |
+
$query_string = substr( $string, stripos( $string, '#' ), strlen( $string ) );
|
239 |
+
array_push( $table_queries, [ trim( $table_name ), ltrim( $query_string, '# <- # ' ) ] );
|
240 |
+
}
|
241 |
+
|
242 |
+
// remove the first (empty) element
|
243 |
+
array_shift( $table_queries );
|
244 |
+
|
245 |
+
return $backup_class->restore_backup_data( $table_queries );
|
246 |
+
} else {
|
247 |
+
return esc_html__( 'A backup file with the selected name does not exists.', 'tvc-product-feed-manager' );
|
248 |
+
}
|
249 |
+
}
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Deletes an existing backup file
|
253 |
+
*
|
254 |
+
* @since 1.7.2
|
255 |
+
*
|
256 |
+
* @param string name of the backup file to be deleted
|
257 |
+
*/
|
258 |
+
public static function delete_backup_file( $backup_file_name ) {
|
259 |
+
$backup_file = TVC_BACKUP_DIR . '/' . $backup_file_name;
|
260 |
+
|
261 |
+
// only return results when the user is an admin with manage options
|
262 |
+
if ( is_admin() ) {
|
263 |
+
/* translators: %s: Selected backup file */
|
264 |
+
echo file_exists( $backup_file ) ? unlink( $backup_file ) : tvc_show_wp_error( sprintf( esc_html__( 'Could not find file %s.', 'tvc-product-feed-manager' ), $backup_file ) );
|
265 |
+
} else {
|
266 |
+
echo tvc_show_wp_error( esc_html__( 'Error deleting the feed. You do not have the correct authorities to delete the file.', 'tvc-product-feed-manager' ) );
|
267 |
+
}
|
268 |
+
}
|
269 |
+
|
270 |
+
/**
|
271 |
+
* Duplicate an existing backup file
|
272 |
+
*
|
273 |
+
* @since 1.7.2
|
274 |
+
*
|
275 |
+
* @param string name of the backup file to be duplicated
|
276 |
+
*/
|
277 |
+
public static function duplicate_backup_file( $backup_file_name ) {
|
278 |
+
$support_class = new TVC_Feed_Support();
|
279 |
+
|
280 |
+
$backup_file_name_without_extension = rtrim( $backup_file_name, '.sql' );
|
281 |
+
$new_backup_file_title = $support_class->next_unique_feed_name( $backup_file_name_without_extension );
|
282 |
+
$new_backup_file_name = $new_backup_file_title . '.sql';
|
283 |
+
|
284 |
+
if ( ! copy( TVC_BACKUP_DIR . '/' . $backup_file_name, TVC_BACKUP_DIR . '/' . $new_backup_file_name ) ) {
|
285 |
+
/* translators: %s: selected backup file name */
|
286 |
+
sprintf( esc_html__( 'Failed to make a copy of %s', 'tvc-product-feed-manager' ), $backup_file_name );
|
287 |
+
} else {
|
288 |
+
echo true;
|
289 |
+
}
|
290 |
+
}
|
291 |
+
|
292 |
+
/**
|
293 |
+
* Clears several options that could hinder a new feed process.
|
294 |
+
*/
|
295 |
+
public static function clean_options_table() {
|
296 |
+
// @since 2.10.0.
|
297 |
+
delete_option( 'tvc_processed_products' );
|
298 |
+
|
299 |
+
$queries_class = new TVC_Queries();
|
300 |
+
$queries_class->clear_feed_batch_options();
|
301 |
+
// also clear the multi site feed batch data
|
302 |
+
if ( is_multisite() ) {
|
303 |
+
$queries_class->clear_feed_batch_sitemeta();
|
304 |
+
}
|
305 |
+
}
|
306 |
+
|
307 |
+
/**
|
308 |
+
* Resets the status_id's of failed feeds.
|
309 |
+
*
|
310 |
+
* @since 2.7.0
|
311 |
+
*/
|
312 |
+
public static function reset_status_of_failed_feeds() {
|
313 |
+
$queries_class = new TVC_Queries();
|
314 |
+
$queries_class->reset_all_feed_status();
|
315 |
+
}
|
316 |
+
|
317 |
+
private static function remove_left_data_part( $data_string ) {
|
318 |
+
$ds = ltrim( $data_string, '#' );
|
319 |
+
|
320 |
+
return substr( $ds, stripos( $ds, '#' ) );
|
321 |
+
}
|
322 |
+
}
|
323 |
+
|
324 |
+
|
325 |
+
endif;
|
includes/data/class-tvc-feed-crud-handler.php
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Feed CRUD Handler class.
|
5 |
+
*
|
6 |
+
* @package TVC Product Feed Manager/Data/Classes
|
7 |
+
* @version 1.0.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Feed_CRUD_Handler' ) ) :
|
15 |
+
|
16 |
+
class TVC_Feed_CRUD_Handler {
|
17 |
+
|
18 |
+
/**
|
19 |
+
* @param $feed_data
|
20 |
+
* @param $meta_data_encoded
|
21 |
+
* @param $feed_filter
|
22 |
+
* @return int
|
23 |
+
*/
|
24 |
+
public static function create_or_update_feed_data( $feed_data, $meta_data_encoded, $feed_filter ) {
|
25 |
+
$data_class = new TVC_Data();
|
26 |
+
$queries_class = new TVC_Queries();
|
27 |
+
|
28 |
+
$feed_id = self::get_feed_id_from_feed_data( $feed_data );
|
29 |
+
|
30 |
+
// convert the feed data to a database format
|
31 |
+
$feed_data_to_store = $data_class->convert_ajax_feed_data_to_database_format( $feed_data );
|
32 |
+
$feed_data_types = $data_class->get_types_from_feed_data( $feed_data_to_store, $feed_data );
|
33 |
+
|
34 |
+
// convert country code to country id
|
35 |
+
$feed_data_to_store['country_id'] = $data_class->get_country_id_from_short_code( $feed_data_to_store['country_id'] )->country_id;
|
36 |
+
|
37 |
+
self::add_fixed_data_fields( $feed_data_to_store, $feed_data_types, $feed_id );
|
38 |
+
|
39 |
+
// decode the meta data
|
40 |
+
$meta_data = json_decode( $meta_data_encoded );
|
41 |
+
|
42 |
+
// create or update the feed
|
43 |
+
if ( $feed_id < 0 ) {
|
44 |
+
$actual_feed_id = $queries_class->create_feed( $feed_data_to_store, $feed_data_types );
|
45 |
+
} else {
|
46 |
+
$update_result = $queries_class->update_feed( $feed_id, $feed_data_to_store, $feed_data_types );
|
47 |
+
$actual_feed_id = $update_result ? $feed_id : 0;
|
48 |
+
}
|
49 |
+
|
50 |
+
if ( count( $meta_data ) > 0 ) {
|
51 |
+
$queries_class->update_meta_data( $actual_feed_id, $meta_data );
|
52 |
+
}
|
53 |
+
|
54 |
+
$queries_class->store_feed_filter( $actual_feed_id, $feed_filter );
|
55 |
+
|
56 |
+
return $actual_feed_id;
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* @param $feed_data
|
61 |
+
* @return mixed
|
62 |
+
*/
|
63 |
+
private static function get_feed_id_from_feed_data( $feed_data ) {
|
64 |
+
// use the array_filter to select the feed data element with product_feed_id as name
|
65 |
+
$feed_id_item = array_filter(
|
66 |
+
$feed_data,
|
67 |
+
function( $element ) {
|
68 |
+
return 'product_feed_id' === $element->name;
|
69 |
+
}
|
70 |
+
);
|
71 |
+
// return the feed id
|
72 |
+
return reset( $feed_id_item )->value;
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* @param $feed_data
|
77 |
+
* @param $data_types
|
78 |
+
* @param $feed_id
|
79 |
+
*/
|
80 |
+
private static function add_fixed_data_fields( &$feed_data, &$data_types, $feed_id ) {
|
81 |
+
$feed_data['updated'] = date( 'Y-m-d H:i:s', current_time( 'timestamp' ) );
|
82 |
+
if ( $feed_id < 0 ) {
|
83 |
+
$feed_data['products'] = 0; }
|
84 |
+
array_push( $data_types, '%s', '%d' );
|
85 |
+
}
|
86 |
+
}
|
87 |
+
// end of TVC_Feed_CRUD_Handler class
|
88 |
+
endif;
|
includes/data/class-tvc-file.php
ADDED
@@ -0,0 +1,246 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* TVC Product Feed File Class.
|
4 |
+
*
|
5 |
+
* @package TVC Product Feed Manager/Data/Classes
|
6 |
+
* @version 1.3.1
|
7 |
+
*/
|
8 |
+
|
9 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
10 |
+
exit;
|
11 |
+
}
|
12 |
+
|
13 |
+
if ( ! class_exists( 'TVC_File' ) ) :
|
14 |
+
|
15 |
+
/**
|
16 |
+
* The File Class
|
17 |
+
*/
|
18 |
+
class TVC_File {
|
19 |
+
|
20 |
+
private $_queries;
|
21 |
+
|
22 |
+
public function __construct() {
|
23 |
+
$this->_queries = new TVC_Queries();
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Reads the correct categories from a channel specific taxonomy text file
|
28 |
+
*
|
29 |
+
* @param int $channel_id
|
30 |
+
* @param string $search_level
|
31 |
+
* @param string $parent_category
|
32 |
+
* @param string $language_code
|
33 |
+
*
|
34 |
+
* @return array|string containing the categories
|
35 |
+
*/
|
36 |
+
public function get_categories_for_list( $channel_id, $search_level, $parent_category, $language_code ) {
|
37 |
+
$channel_class = new TVC_Channel();
|
38 |
+
|
39 |
+
$last_cat = '';
|
40 |
+
$categories = array();
|
41 |
+
$channel_name = $channel_class->get_channel_short_name( $channel_id );
|
42 |
+
|
43 |
+
$path = TVC_CHANNEL_DATA_DIR . "/$channel_name/taxonomy.$language_code.txt";
|
44 |
+
|
45 |
+
if ( file_exists( $path ) ) {
|
46 |
+
$file = fopen( $path, 'r' )
|
47 |
+
or die( esc_html__( 'Unable to open the file containing the categories', 'tvc-product-feed-manager' ) );
|
48 |
+
|
49 |
+
// step over the first lines that do not contain categories
|
50 |
+
while ( strpos( fgets( $file ), '#' ) ) {
|
51 |
+
continue;
|
52 |
+
}
|
53 |
+
|
54 |
+
// step through all the lines in the file
|
55 |
+
while ( ! feof( $file ) ) {
|
56 |
+
// get the line
|
57 |
+
$line = trim( fgets( $file ) );
|
58 |
+
|
59 |
+
// split the line into pieces using the > separator
|
60 |
+
$category_line_array = explode( '>', $line );
|
61 |
+
|
62 |
+
if ( 0 === $search_level ) {
|
63 |
+
if ( trim( $category_line_array [ $search_level ] ) !== $last_cat ) {
|
64 |
+
array_push( $categories, trim( $category_line_array [ $search_level ] ) );
|
65 |
+
$last_cat = trim( $category_line_array [ $search_level ] );
|
66 |
+
}
|
67 |
+
} elseif ( count( $category_line_array ) > $search_level && $search_level > 0 && trim( $category_line_array [ $search_level - 1 ] ) === trim( $parent_category ) ) {
|
68 |
+
if ( trim( $category_line_array [ $search_level ] ) !== $last_cat ) {
|
69 |
+
array_push( $categories, trim( $category_line_array [ $search_level ] ) );
|
70 |
+
$last_cat = trim( $category_line_array [ $search_level ] );
|
71 |
+
}
|
72 |
+
}
|
73 |
+
}
|
74 |
+
|
75 |
+
// don't forget to free the resources
|
76 |
+
fclose( $file );
|
77 |
+
}
|
78 |
+
|
79 |
+
return $categories;
|
80 |
+
}
|
81 |
+
|
82 |
+
public function get_output_fields_for_specific_channel( $channel ) {
|
83 |
+
$fields = array();
|
84 |
+
|
85 |
+
$path = TVC_CHANNEL_DATA_DIR . "/$channel/$channel.txt";
|
86 |
+
|
87 |
+
if ( file_exists( $path ) ) {
|
88 |
+
$file = fopen( $path, 'r' )
|
89 |
+
or die( esc_html__( 'Unable to open the file containing the categories', 'tvc-product-feed-manager' ) );
|
90 |
+
|
91 |
+
// step through all the lines in the file
|
92 |
+
while ( ! feof( $file ) ) {
|
93 |
+
$field_object = new stdClass();
|
94 |
+
|
95 |
+
// get the line
|
96 |
+
$line = fgetcsv( $file, 0, "\t" );
|
97 |
+
|
98 |
+
if ( is_array( $line ) && ! empty( $line[0] ) ) {
|
99 |
+
$field_object->field_id = $line[0];
|
100 |
+
$field_object->category_id = $line[1];
|
101 |
+
$field_object->field_label = $line[2];
|
102 |
+
|
103 |
+
array_push( $fields, $field_object );
|
104 |
+
}
|
105 |
+
}
|
106 |
+
}
|
107 |
+
|
108 |
+
return $fields;
|
109 |
+
}
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Check the standard backup folder and return the .sql file names in it
|
113 |
+
*
|
114 |
+
* @return array
|
115 |
+
*/
|
116 |
+
public function make_list_of_active_backups() {
|
117 |
+
$backups = array();
|
118 |
+
|
119 |
+
$path = TVC_BACKUP_DIR;
|
120 |
+
|
121 |
+
foreach ( glob( $path . '/*.sql' ) as $file ) {
|
122 |
+
$feed = fopen( $file, 'r' );
|
123 |
+
$line = fgets( $feed );
|
124 |
+
fclose( $feed );
|
125 |
+
|
126 |
+
$file_name = str_replace( TVC_BACKUP_DIR . '/', '', $file );
|
127 |
+
$date_string = strtok( $line, '#' );
|
128 |
+
$file_date = strlen( $date_string ) < 15 ? date( 'Y-m-d H:i:s', $date_string ) : 'unknown';
|
129 |
+
|
130 |
+
array_push( $backups, $file_name . '&&' . $file_date );
|
131 |
+
}
|
132 |
+
|
133 |
+
return $backups;
|
134 |
+
}
|
135 |
+
|
136 |
+
public function write_full_backup_file( $backup_file, $backup_string ) {
|
137 |
+
if ( is_writable( TVC_BACKUP_DIR ) ) {
|
138 |
+
$feed = fopen( $backup_file, 'w' );
|
139 |
+
} else {
|
140 |
+
/* translators: %s: Folder that holds the backup files */
|
141 |
+
return sprintf( esc_html__( '1432 - %s is not a writable folder. Make sure you have admin rights to this folder.', 'tvc-product-feed-manager' ), TVC_BACKUP_DIR );
|
142 |
+
}
|
143 |
+
|
144 |
+
if ( false !== $feed ) {
|
145 |
+
fwrite( $feed, $backup_string );
|
146 |
+
fclose( $feed );
|
147 |
+
|
148 |
+
return true;
|
149 |
+
} else {
|
150 |
+
/* translators: %s: Selected backup file */
|
151 |
+
return sprintf( esc_html__( '1433 - Could not write the %s file.', 'tvc-product-feed-manager' ), $backup_file );
|
152 |
+
}
|
153 |
+
}
|
154 |
+
|
155 |
+
public function get_installed_channels_from_file() {
|
156 |
+
$active_channels = array();
|
157 |
+
|
158 |
+
if ( file_exists( TVC_CHANNEL_DATA_DIR ) ) {
|
159 |
+
$dir_iterator = new RecursiveDirectoryIterator( TVC_CHANNEL_DATA_DIR );
|
160 |
+
$iterator = new RecursiveIteratorIterator( $dir_iterator, RecursiveIteratorIterator::SELF_FIRST );
|
161 |
+
|
162 |
+
foreach ( $iterator as $folder ) {
|
163 |
+
if ( $folder->isDir() && $folder->getFilename() !== '.' & $folder->getFilename() !== '..' ) {
|
164 |
+
array_push( $active_channels, $folder->getBaseName() );
|
165 |
+
}
|
166 |
+
}
|
167 |
+
}
|
168 |
+
|
169 |
+
return $active_channels;
|
170 |
+
}
|
171 |
+
|
172 |
+
/**
|
173 |
+
* Takes the installed channel .zip file and unzips it in the channels folder
|
174 |
+
*
|
175 |
+
* @param string $channel_name
|
176 |
+
*
|
177 |
+
* @return bool false if installing the channel failed
|
178 |
+
*/
|
179 |
+
public function unzip_channel_file( $channel_name ) {
|
180 |
+
if ( ! file_exists( TVC_CHANNEL_DATA_DIR ) ) {
|
181 |
+
TVC_Folders::make_channels_support_folder();
|
182 |
+
}
|
183 |
+
|
184 |
+
WP_Filesystem();
|
185 |
+
|
186 |
+
$zip_file = TVC_CHANNEL_DATA_DIR . '/' . $channel_name . '.zip';
|
187 |
+
$destination_path = TVC_CHANNEL_DATA_DIR . '/';
|
188 |
+
|
189 |
+
if ( ! file_exists( $zip_file ) ) {
|
190 |
+
tvc_write_log_file( sprintf( 'Failed installing the Channel %s. Could not download the .zip file from the server.', $channel_name ) );
|
191 |
+
|
192 |
+
return false;
|
193 |
+
}
|
194 |
+
|
195 |
+
$unzip_result = unzip_file( $zip_file, $destination_path );
|
196 |
+
|
197 |
+
if ( is_wp_error( $unzip_result ) ) {
|
198 |
+
tvc_handle_wp_errors_response( $unzip_result, sprintf( 'The installation of channel %s failed. Unable to unpack the channel file in folder %s.', $channel_name, TVC_CHANNEL_DATA_DIR ) );
|
199 |
+
}
|
200 |
+
|
201 |
+
unlink( $zip_file ); // clean up the zip file
|
202 |
+
|
203 |
+
return true;
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* @param $channel_short_name
|
208 |
+
*/
|
209 |
+
public function delete_channel_source_files( $channel_short_name ) {
|
210 |
+
$channel_folder = TVC_CHANNEL_DATA_DIR . '/' . $channel_short_name;
|
211 |
+
|
212 |
+
if ( file_exists( $channel_folder ) && is_dir( $channel_folder ) ) {
|
213 |
+
// remove the channel definition files
|
214 |
+
TVC_Folders::delete_folder( $channel_folder );
|
215 |
+
}
|
216 |
+
|
217 |
+
if ( 'google' === $channel_short_name ) {
|
218 |
+
$free_version_google_folder = ENHANCAD_PLUGIN_DIR . 'includes/application/google';
|
219 |
+
|
220 |
+
if ( file_exists( $free_version_google_folder ) && is_dir( $free_version_google_folder ) ) {
|
221 |
+
TVC_Folders::delete_folder( $free_version_google_folder );
|
222 |
+
}
|
223 |
+
}
|
224 |
+
}
|
225 |
+
|
226 |
+
/**
|
227 |
+
* @param $channel_id
|
228 |
+
*/
|
229 |
+
public function delete_channel_feed_files( $channel_id ) {
|
230 |
+
$feeds = $this->_queries->get_feeds_from_specific_channel( $channel_id );
|
231 |
+
|
232 |
+
foreach ( $feeds as $feed_id ) {
|
233 |
+
$file_url = $this->_queries->get_file_url_from_feed( $feed_id['product_feed_id'] );
|
234 |
+
$file_name = basename( $file_url );
|
235 |
+
$file_path = TVC_FEEDS_DIR . '/' . $file_name;
|
236 |
+
|
237 |
+
if ( file_exists( $file_path ) ) {
|
238 |
+
unlink( $file_path );
|
239 |
+
}
|
240 |
+
}
|
241 |
+
}
|
242 |
+
}
|
243 |
+
|
244 |
+
// end of TVC_File_Class
|
245 |
+
|
246 |
+
endif;
|
includes/data/class-tvc-queries.php
ADDED
@@ -0,0 +1,970 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Queries Class.
|
5 |
+
*
|
6 |
+
* @package TVC Product Feed Manager/Data/Classes
|
7 |
+
* @version 4.11.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Queries' ) ) :
|
15 |
+
|
16 |
+
/**
|
17 |
+
* WP Queries Class
|
18 |
+
*/
|
19 |
+
class TVC_Queries {
|
20 |
+
|
21 |
+
private $_wpdb;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* @var string placeholder containing the wp table prefix
|
25 |
+
*/
|
26 |
+
private $_table_prefix;
|
27 |
+
|
28 |
+
/**
|
29 |
+
* TVC_Queries Constructor
|
30 |
+
*/
|
31 |
+
public function __construct() {
|
32 |
+
// get global WordPress database functions
|
33 |
+
global $wpdb;
|
34 |
+
|
35 |
+
// assign the global wpdb to a variable
|
36 |
+
$this->_wpdb = &$wpdb;
|
37 |
+
|
38 |
+
// assign the wp table prefix to a variable
|
39 |
+
$this->_table_prefix = $this->_wpdb->prefix;
|
40 |
+
}
|
41 |
+
|
42 |
+
public function get_feeds_list() {
|
43 |
+
// filter out all non product feeds when no special feed add-on plugin is active
|
44 |
+
$feed_type_filter = ! apply_filters( 'tvc_special_feeds_add_on_active', false ) ? " WHERE p.feed_type_id = '1'" : '';
|
45 |
+
|
46 |
+
return $this->_wpdb->get_results(
|
47 |
+
"SELECT p.product_feed_id, p.title, p.url, p.updated, p.feed_type_id, p.products, s.status AS status, s.color AS color FROM {$this->_table_prefix}feedmanager_product_feed AS p
|
48 |
+
INNER JOIN {$this->_table_prefix}feedmanager_feed_status AS s on p.status_id = s.status_id{$feed_type_filter}"
|
49 |
+
);
|
50 |
+
}
|
51 |
+
|
52 |
+
public function get_all_feed_names() {
|
53 |
+
return $this->_wpdb->get_results( "SELECT title FROM {$this->_table_prefix}feedmanager_product_feed" );
|
54 |
+
}
|
55 |
+
|
56 |
+
public function get_feed_row( $feed_id ) {
|
57 |
+
return $this->_wpdb->get_row( "SELECT * FROM {$this->_table_prefix}feedmanager_product_feed WHERE product_feed_id = {$feed_id}" );
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Get a list of all existing countries
|
62 |
+
*
|
63 |
+
* @return array|object|null of the query
|
64 |
+
*/
|
65 |
+
public function read_countries() {
|
66 |
+
return $this->_wpdb->get_results( "SELECT name_short, name FROM {$this->_table_prefix}feedmanager_country ORDER BY name", ARRAY_A );
|
67 |
+
}
|
68 |
+
|
69 |
+
public function get_feedmanager_channel_table() {
|
70 |
+
return $this->_wpdb->get_results( "SELECT * FROM {$this->_table_prefix}feedmanager_channel", ARRAY_A );
|
71 |
+
}
|
72 |
+
|
73 |
+
public function get_feedmanager_product_feed_table() {
|
74 |
+
return $this->_wpdb->get_results( "SELECT * FROM {$this->_table_prefix}feedmanager_product_feed", ARRAY_A );
|
75 |
+
}
|
76 |
+
|
77 |
+
public function get_feedmanager_product_feedmeta_table() {
|
78 |
+
return $this->_wpdb->get_results( "SELECT * FROM {$this->_table_prefix}feedmanager_product_feedmeta", ARRAY_A );
|
79 |
+
}
|
80 |
+
|
81 |
+
public function get_feed_type_id( $feed_id ) {
|
82 |
+
return $this->_wpdb->get_var( "SELECT feed_type_id FROM {$this->_table_prefix}feedmanager_product_feed WHERE product_feed_id = '{$feed_id}'" );
|
83 |
+
}
|
84 |
+
|
85 |
+
public function read_channels() {
|
86 |
+
$google = array( 'channel_id' => '1', 'name' => 'Google Merchant Centre', 'short' => 'google' );
|
87 |
+
return array( $google );
|
88 |
+
}
|
89 |
+
public function get_set_merchant_id(){
|
90 |
+
return $this->_wpdb->get_var( "SELECT * FROM {$this->_table_prefix}feedmanager_default_center WHERE status = 1" );
|
91 |
+
}
|
92 |
+
|
93 |
+
public function get_merchant_info(){
|
94 |
+
return $this->_wpdb->get_row( "SELECT * FROM {$this->_table_prefix}feedmanager_default_center WHERE status = 1");
|
95 |
+
}
|
96 |
+
|
97 |
+
public function get_set_ads_account_id($merchantId = ''){
|
98 |
+
if($merchantId == '') {
|
99 |
+
return $this->_wpdb->get_var( "SELECT * FROM {$this->_table_prefix}adsmanager_default_center WHERE status = 1" );
|
100 |
+
} else {
|
101 |
+
return $this->_wpdb->get_var( "SELECT * FROM {$this->_table_prefix}adsmanager_default_center WHERE status = 1 AND merchant_id = {$merchantId}" );
|
102 |
+
}
|
103 |
+
|
104 |
+
}
|
105 |
+
|
106 |
+
public function get_merchant_center_linked_flag($adsId = '') {
|
107 |
+
return $this->_wpdb->get_row( "SELECT * FROM {$this->_table_prefix}adsmanager_default_center WHERE status = 1 AND merchant_center_linked = 1 AND account_id = {$adsId}" );
|
108 |
+
}
|
109 |
+
|
110 |
+
public function get_claim(){
|
111 |
+
return $this->_wpdb->get_var( "SELECT * FROM {$this->_table_prefix}feedmanager_default_center WHERE claim = 1" );
|
112 |
+
}
|
113 |
+
|
114 |
+
/**
|
115 |
+
* @param $channel_short_name
|
116 |
+
* @param $channel_id
|
117 |
+
* @param $channel_name
|
118 |
+
* @return bool|int
|
119 |
+
*/
|
120 |
+
public function register_a_channel( $channel_short_name, $channel_id, $channel_name ) {
|
121 |
+
return $this->_wpdb->query(
|
122 |
+
$this->_wpdb->prepare(
|
123 |
+
"INSERT INTO {$this->_table_prefix}feedmanager_channel (channel_id, name, short) VALUES
|
124 |
+
( %d, '%s', '%s' )",
|
125 |
+
$channel_id,
|
126 |
+
$channel_name,
|
127 |
+
$channel_short_name
|
128 |
+
)
|
129 |
+
);
|
130 |
+
}
|
131 |
+
|
132 |
+
/**
|
133 |
+
* @param $channel_short_name
|
134 |
+
* @return string|null
|
135 |
+
*/
|
136 |
+
public function get_channel_id( $channel_short_name ) {
|
137 |
+
return $this->_wpdb->get_var( "SELECT channel_id FROM {$this->_table_prefix}feedmanager_channel WHERE short = '{$channel_short_name}'" );
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* @param $channel_id
|
142 |
+
* @return bool|string|null
|
143 |
+
*/
|
144 |
+
public function get_channel_short_name_from_db( $channel_id ) {
|
145 |
+
if ( 'undefined' !== $channel_id ) { // make sure the selected channel is installed
|
146 |
+
return $this->_wpdb->get_var( "SELECT short FROM {$this->_table_prefix}feedmanager_channel WHERE channel_id = {$channel_id}" );
|
147 |
+
} else {
|
148 |
+
return false;
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* @param $channel_short
|
154 |
+
* @return false|int
|
155 |
+
*/
|
156 |
+
public function remove_channel_from_db( $channel_short ) {
|
157 |
+
$main_table = $this->_table_prefix . 'feedmanager_channel';
|
158 |
+
|
159 |
+
return $this->_wpdb->delete( $main_table, array( 'short' => $channel_short ) );
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* @return bool|int
|
164 |
+
*/
|
165 |
+
public function clean_channel_table() {
|
166 |
+
return $this->_wpdb->query(
|
167 |
+
$this->_wpdb->prepare(
|
168 |
+
"DELETE FROM {$this->_table_prefix}feedmanager_channel WHERE channel_id = %d OR name = %s",
|
169 |
+
0,
|
170 |
+
''
|
171 |
+
)
|
172 |
+
);
|
173 |
+
}
|
174 |
+
|
175 |
+
public function read_active_schedule_data() {
|
176 |
+
return $this->_wpdb->get_results( "SELECT product_feed_id, updated, schedule FROM {$this->_table_prefix}feedmanager_product_feed WHERE status_id=1", ARRAY_A );
|
177 |
+
}
|
178 |
+
|
179 |
+
public function read_failed_feeds() {
|
180 |
+
return $this->_wpdb->get_results( "SELECT product_feed_id, updated, schedule FROM {$this->_table_prefix}feedmanager_product_feed WHERE status_id=5 OR status_id=6", ARRAY_A );
|
181 |
+
}
|
182 |
+
|
183 |
+
public function read_sources() {
|
184 |
+
return $this->_wpdb->get_results( "SELECT source_id, name FROM {$this->_table_prefix}feedmanager_source ORDER BY name", ARRAY_A );
|
185 |
+
}
|
186 |
+
|
187 |
+
public function get_feeds_from_specific_channel( $channel_id ) {
|
188 |
+
return $this->_wpdb->get_results( "SELECT product_feed_id FROM {$this->_table_prefix}feedmanager_product_feed WHERE channel_id = {$channel_id}", ARRAY_A );
|
189 |
+
}
|
190 |
+
|
191 |
+
/**
|
192 |
+
* @param $feed_id
|
193 |
+
* @return array|object|null
|
194 |
+
*/
|
195 |
+
public function get_meta_parents( $feed_id ) {
|
196 |
+
return $this->_wpdb->get_results( "SELECT ID FROM {$this->_table_prefix}posts WHERE post_parent = {$feed_id}", ARRAY_A );
|
197 |
+
}
|
198 |
+
|
199 |
+
/**
|
200 |
+
* @param $feed_id
|
201 |
+
* @return array|object|null
|
202 |
+
*/
|
203 |
+
public function read_feed( $feed_id ) {
|
204 |
+
$result = $this->_wpdb->get_results(
|
205 |
+
"SELECT p.product_feed_id, p.source_id AS source, p.title, p.feed_title, p.feed_description, p.main_category, "
|
206 |
+
. "p.url, p.include_variations, p.is_aggregator, p.status_id, p.base_status_id, p.updated, p.products, p.feed_type_id, p.schedule, c.name_short "
|
207 |
+
. "AS country, m.channel_id AS channel, p.language "
|
208 |
+
. "FROM {$this->_table_prefix}feedmanager_product_feed AS p "
|
209 |
+
. "INNER JOIN {$this->_table_prefix}feedmanager_country AS c ON p.country_id = c.country_id "
|
210 |
+
. "INNER JOIN {$this->_table_prefix}feedmanager_channel AS m ON p.channel_id = m.channel_id "
|
211 |
+
. "WHERE p.product_feed_id = {$feed_id}",
|
212 |
+
ARRAY_A
|
213 |
+
);
|
214 |
+
|
215 |
+
$category_mapping = $this->read_category_mapping( $feed_id );
|
216 |
+
|
217 |
+
if ( isset( $category_mapping[0]['meta_value'] ) && $category_mapping[0]['meta_value'] !== '' ) {
|
218 |
+
$result[0]['category_mapping'] = $category_mapping[0]['meta_value'];
|
219 |
+
} else {
|
220 |
+
$result[0]['category_mapping'] = '';
|
221 |
+
}
|
222 |
+
|
223 |
+
return $result;
|
224 |
+
}
|
225 |
+
|
226 |
+
/**
|
227 |
+
* @param $feed_id
|
228 |
+
* @return array|object|null
|
229 |
+
*/
|
230 |
+
public function read_category_mapping( $feed_id ) {
|
231 |
+
return $this->_wpdb->get_results( "SELECT meta_value FROM {$this->_table_prefix}feedmanager_product_feedmeta WHERE product_feed_id = {$feed_id} AND meta_key = 'category_mapping'", ARRAY_A );
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* @param $feed_id
|
236 |
+
* @return |null
|
237 |
+
*/
|
238 |
+
public function get_feed_status_data( $feed_id ) {
|
239 |
+
$status = $this->_wpdb->get_results(
|
240 |
+
"SELECT product_feed_id, channel_id, title, url, status_id, products, feed_type_id "
|
241 |
+
. "FROM {$this->_table_prefix}feedmanager_product_feed "
|
242 |
+
. "WHERE product_feed_id = '{$feed_id}'",
|
243 |
+
ARRAY_A
|
244 |
+
);
|
245 |
+
|
246 |
+
return $status ? $status[0] : null;
|
247 |
+
}
|
248 |
+
|
249 |
+
/**
|
250 |
+
* Returns the post ids that belong to the selected categories
|
251 |
+
*
|
252 |
+
* @param string $category_string A string that contains the selected categories.
|
253 |
+
* @param bool $with_variation True if product variations should be included in the feed. Default false.
|
254 |
+
*
|
255 |
+
* @return array
|
256 |
+
*/
|
257 |
+
public function get_post_ids( $category_string, $with_variation = false ) {
|
258 |
+
// If the user has not selected a category, return an empty array.
|
259 |
+
if ( empty( $category_string ) ) {
|
260 |
+
return array();
|
261 |
+
}
|
262 |
+
|
263 |
+
$start_product_id = get_transient( 'tvc_start_product_id' ) ? get_transient( 'tvc_start_product_id' ) : -1;
|
264 |
+
|
265 |
+
// Limit the number of products per query to 1000 to prevent a result that is to large to handle by the server.
|
266 |
+
// When the limit is reached a next batch will be requested by the fill_the_background_queue function.
|
267 |
+
// @since 2.11.0
|
268 |
+
$product_query_limit = apply_filters( 'tvc_product_query_limit', 1000 );
|
269 |
+
|
270 |
+
$products_query = "SELECT DISTINCT {$this->_table_prefix}posts.ID
|
271 |
+
FROM {$this->_table_prefix}posts
|
272 |
+
LEFT JOIN {$this->_table_prefix}term_relationships ON ({$this->_table_prefix}posts.ID = {$this->_table_prefix}term_relationships.object_id)
|
273 |
+
LEFT JOIN {$this->_table_prefix}term_taxonomy ON ({$this->_table_prefix}term_relationships.term_taxonomy_id = {$this->_table_prefix}term_taxonomy.term_taxonomy_id)
|
274 |
+
WHERE {$this->_table_prefix}posts.post_type = 'product' AND {$this->_table_prefix}posts.post_status = 'publish'
|
275 |
+
AND {$this->_table_prefix}term_taxonomy.term_id IN ($category_string)
|
276 |
+
AND {$this->_table_prefix}posts.ID > $start_product_id
|
277 |
+
ORDER BY ID LIMIT $product_query_limit";
|
278 |
+
|
279 |
+
// Get all main product ids (simple and variable, but not the variations).
|
280 |
+
$main_products_ids = $this->_wpdb->get_col( $products_query );
|
281 |
+
|
282 |
+
set_transient( 'tvc_start_product_id', end( $main_products_ids ), TVC_TRANSIENT_LIVE );
|
283 |
+
|
284 |
+
// if variations should not be included return the main product ids
|
285 |
+
if ( ! $with_variation || empty( $main_products_ids ) ) {
|
286 |
+
return $main_products_ids;
|
287 |
+
}
|
288 |
+
|
289 |
+
// Put the main ids in a string so it can be attached to a query string.
|
290 |
+
$main_products_ids_string = implode( ', ', $main_products_ids );
|
291 |
+
|
292 |
+
$variation_products_query = "SELECT DISTINCT post_parent FROM {$this->_table_prefix}posts
|
293 |
+
WHERE {$this->_table_prefix}posts.post_parent IN ( {$main_products_ids_string} )
|
294 |
+
AND {$this->_table_prefix}posts.post_type = 'product_variation'
|
295 |
+
AND {$this->_table_prefix}posts.post_status = 'publish'
|
296 |
+
ORDER BY ID";
|
297 |
+
|
298 |
+
// Get the ids of the variable products.
|
299 |
+
$variation_products = $this->_wpdb->get_col( $variation_products_query );
|
300 |
+
|
301 |
+
// If there are no variations, return the main product ids.
|
302 |
+
if ( count( $variation_products ) < 1 ) {
|
303 |
+
return $main_products_ids;
|
304 |
+
}
|
305 |
+
|
306 |
+
$variation_products_ids_string = implode( ', ', $variation_products );
|
307 |
+
|
308 |
+
// Remove the main product ids of products that have a valid variable version from the list to keep only the ids of the simple products.
|
309 |
+
$simple_products_ids = array_diff( $main_products_ids, $variation_products );
|
310 |
+
|
311 |
+
$product_variations_query = "SELECT DISTINCT ID FROM {$this->_table_prefix}posts
|
312 |
+
WHERE {$this->_table_prefix}posts.post_parent IN ( {$variation_products_ids_string} )
|
313 |
+
AND {$this->_table_prefix}posts.post_type = 'product_variation'
|
314 |
+
AND {$this->_table_prefix}posts.post_status = 'publish'
|
315 |
+
ORDER BY ID";
|
316 |
+
|
317 |
+
// Now get the variations.
|
318 |
+
$product_variations_ids = $this->_wpdb->get_col( $product_variations_query );
|
319 |
+
|
320 |
+
// Combine the variable product ids with the remaining simple product ids.
|
321 |
+
$all_product_ids = array_merge( $simple_products_ids, $product_variations_ids );
|
322 |
+
asort( $all_product_ids );
|
323 |
+
|
324 |
+
return $all_product_ids;
|
325 |
+
}
|
326 |
+
|
327 |
+
/**
|
328 |
+
* Gets the required data from the main
|
329 |
+
*
|
330 |
+
* @param string $post_id
|
331 |
+
* @param string $column_string
|
332 |
+
*
|
333 |
+
* @return array|object|null
|
334 |
+
*/
|
335 |
+
public function read_post_data( $post_id, $column_string ) {
|
336 |
+
$selecting_columns = $column_string ? ', ' . $column_string : '';
|
337 |
+
|
338 |
+
$result = $this->_wpdb->get_results(
|
339 |
+
"SELECT DISTINCT ID $selecting_columns
|
340 |
+
FROM {$this->_table_prefix}posts
|
341 |
+
WHERE ID = $post_id"
|
342 |
+
);
|
343 |
+
|
344 |
+
return $result ? $result[0] : null;
|
345 |
+
}
|
346 |
+
|
347 |
+
/**
|
348 |
+
* returns the lowest product id belonging to one or more categories
|
349 |
+
*
|
350 |
+
* @param string $category_string
|
351 |
+
*
|
352 |
+
* @return string
|
353 |
+
*/
|
354 |
+
public function get_lowest_product_id( $category_string ) {
|
355 |
+
$main_table = $this->_table_prefix . 'posts';
|
356 |
+
$term_relationships_table = $this->_table_prefix . 'term_relationships';
|
357 |
+
$term_taxonomy_table = $this->_table_prefix . 'term_taxonomy';
|
358 |
+
|
359 |
+
$result = $this->_wpdb->get_results(
|
360 |
+
"SELECT MIN(ID) FROM $main_table
|
361 |
+
LEFT JOIN $term_relationships_table ON ($main_table.ID = $term_relationships_table.object_id)
|
362 |
+
LEFT JOIN $term_taxonomy_table ON ($term_relationships_table.term_taxonomy_id = $term_taxonomy_table.term_taxonomy_id)
|
363 |
+
WHERE $main_table.post_type = 'product' AND $main_table.post_status = 'publish'
|
364 |
+
AND $term_taxonomy_table.term_id IN ($category_string)",
|
365 |
+
ARRAY_A
|
366 |
+
);
|
367 |
+
|
368 |
+
return $result ? $result[0]['MIN(ID)'] : 0;
|
369 |
+
}
|
370 |
+
|
371 |
+
|
372 |
+
/**
|
373 |
+
* returns the highest product id belonging to one or more categories
|
374 |
+
*
|
375 |
+
* @param string $category_string
|
376 |
+
*
|
377 |
+
* @return string
|
378 |
+
*/
|
379 |
+
public function get_highest_product_id( $category_string ) {
|
380 |
+
$main_table = $this->_table_prefix . 'posts';
|
381 |
+
$term_relationships_table = $this->_table_prefix . 'term_relationships';
|
382 |
+
$term_taxonomy_table = $this->_table_prefix . 'term_taxonomy';
|
383 |
+
|
384 |
+
$result = $this->_wpdb->get_results(
|
385 |
+
"SELECT MAX(ID) FROM $main_table
|
386 |
+
LEFT JOIN $term_relationships_table ON ($main_table.ID = $term_relationships_table.object_id)
|
387 |
+
LEFT JOIN $term_taxonomy_table ON ($term_relationships_table.term_taxonomy_id = $term_taxonomy_table.term_taxonomy_id)
|
388 |
+
WHERE $main_table.post_type = 'product' AND $main_table.post_status = 'publish'
|
389 |
+
AND $term_taxonomy_table.term_id IN ($category_string)",
|
390 |
+
ARRAY_A
|
391 |
+
);
|
392 |
+
|
393 |
+
return $result ? $result[0]['MAX(ID)'] : 0;
|
394 |
+
}
|
395 |
+
|
396 |
+
/**
|
397 |
+
* @param $product_id
|
398 |
+
* @param $parent_product_id
|
399 |
+
* @param $record_ids
|
400 |
+
* @param $meta_columns
|
401 |
+
* @return array
|
402 |
+
*/
|
403 |
+
public function read_meta_data( $product_id, $parent_product_id, $record_ids, $meta_columns ) {
|
404 |
+
$data = array();
|
405 |
+
|
406 |
+
foreach ( $meta_columns as $column ) {
|
407 |
+
$taxonomy = get_taxonomy( $column );
|
408 |
+
|
409 |
+
if ( $taxonomy ) {
|
410 |
+
|
411 |
+
$taxonomy_value = TVC_Taxonomies::make_shop_taxonomies_string( $product_id, $taxonomy->name, ', ' );
|
412 |
+
|
413 |
+
if ( ! $taxonomy_value ) {
|
414 |
+
$taxonomy_value = TVC_Taxonomies::make_shop_taxonomies_string( $parent_product_id, $taxonomy->name, ', ' );
|
415 |
+
}
|
416 |
+
|
417 |
+
if ( $taxonomy_value ) {
|
418 |
+
array_push( $data, $this->make_meta_object( $column, $taxonomy_value, $product_id ) );
|
419 |
+
}
|
420 |
+
}
|
421 |
+
|
422 |
+
foreach ( $record_ids as $rec_id ) {
|
423 |
+
$value = get_post_meta( $rec_id, $column, true );
|
424 |
+
|
425 |
+
if ( $value || '0' === $value ) {
|
426 |
+
array_push( $data, $this->make_meta_object( $column, $value, $rec_id ) );
|
427 |
+
break;
|
428 |
+
} else {
|
429 |
+
$alt_val = maybe_unserialize( get_post_meta( $rec_id, '_product_attributes', true ) );
|
430 |
+
$col_name = str_replace( ' ', '-', strtolower( $column ) );
|
431 |
+
if ( $alt_val && isset( $alt_val[ $col_name ] ) ) {
|
432 |
+
array_push( $data, $this->make_meta_object( $column, $alt_val[ $col_name ]['value'], $rec_id ) );
|
433 |
+
} elseif ( $alt_val && is_array( $alt_val ) ) {
|
434 |
+
foreach ( $alt_val as $v ) {
|
435 |
+
if ( $v['name'] === $column ) {
|
436 |
+
array_push( $data, $this->make_meta_object( $column, $v['value'], $rec_id ) );
|
437 |
+
}
|
438 |
+
}
|
439 |
+
}
|
440 |
+
}
|
441 |
+
}
|
442 |
+
}
|
443 |
+
|
444 |
+
$this->polish_data( $data, $product_id );
|
445 |
+
|
446 |
+
return $data;
|
447 |
+
}
|
448 |
+
|
449 |
+
/**
|
450 |
+
* @param $key
|
451 |
+
* @param $value
|
452 |
+
* @param $id
|
453 |
+
* @return stdClass
|
454 |
+
*/
|
455 |
+
private function make_meta_object( $key, $value, $id ) {
|
456 |
+
$obj = new stdClass();
|
457 |
+
$obj->meta_key = $key;
|
458 |
+
$obj->meta_value = $value;
|
459 |
+
$obj->post_id = $id;
|
460 |
+
|
461 |
+
return $obj;
|
462 |
+
}
|
463 |
+
|
464 |
+
/**
|
465 |
+
* @param $data
|
466 |
+
* @param $main_post_id
|
467 |
+
*/
|
468 |
+
private function polish_data( &$data, $main_post_id ) {
|
469 |
+
$site_url = get_option( 'siteurl' );
|
470 |
+
|
471 |
+
foreach ( $data as $row ) {
|
472 |
+
// make sure the _wp_attached_file data contains a valid url
|
473 |
+
if ( '_wp_attached_file' === $row->meta_key ) {
|
474 |
+
$row->meta_value = $this->get_post_thumbnail_url( $main_post_id, 'large' );
|
475 |
+
|
476 |
+
// if the _wp_attached_file data is not a valid url than add the url data
|
477 |
+
if ( ! filter_var( $row->meta_value, FILTER_VALIDATE_URL ) ) {
|
478 |
+
$row->meta_value = $site_url . '/wp-content/uploads/' . $row->meta_value;
|
479 |
+
}
|
480 |
+
}
|
481 |
+
|
482 |
+
// convert the time stamp format to a usable date time format for the feed
|
483 |
+
if ( '_sale_price_dates_from' === $row->meta_key || '_sale_price_dates_to' === $row->meta_key ) {
|
484 |
+
$row->meta_value = tvc_convert_price_date_to_feed_format( $row->meta_value );
|
485 |
+
}
|
486 |
+
}
|
487 |
+
}
|
488 |
+
|
489 |
+
/**
|
490 |
+
* @param $feed_id
|
491 |
+
* @return false|int
|
492 |
+
*/
|
493 |
+
public function delete_feed( $feed_id ) {
|
494 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
495 |
+
|
496 |
+
return $this->_wpdb->delete( $main_table, array( 'product_feed_id' => $feed_id ) );
|
497 |
+
}
|
498 |
+
|
499 |
+
/**
|
500 |
+
* @param $feed_id
|
501 |
+
* @return false|int
|
502 |
+
*/
|
503 |
+
public function delete_meta( $feed_id ) {
|
504 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feedmeta';
|
505 |
+
|
506 |
+
return $this->_wpdb->delete( $main_table, array( 'product_feed_id' => $feed_id ) );
|
507 |
+
}
|
508 |
+
|
509 |
+
/**
|
510 |
+
* Gets the meta data from a specific feed. It does not include the category mapping and feed filter data.
|
511 |
+
*
|
512 |
+
* @param string $feed_id
|
513 |
+
*
|
514 |
+
* @return array|bool|object|null
|
515 |
+
*/
|
516 |
+
public function read_metadata( $feed_id ) {
|
517 |
+
if ( $feed_id ) {
|
518 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feedmeta';
|
519 |
+
|
520 |
+
return $this->_wpdb->get_results( "SELECT * FROM $main_table WHERE product_feed_id = $feed_id AND meta_key != 'category_mapping' AND meta_key != 'product_filter_query' ORDER BY meta_id", ARRAY_A );
|
521 |
+
} else {
|
522 |
+
return false;
|
523 |
+
}
|
524 |
+
}
|
525 |
+
|
526 |
+
/**
|
527 |
+
* Fetches the Feed Filter data from a specific feed.
|
528 |
+
*
|
529 |
+
* @param string $feed_id
|
530 |
+
*
|
531 |
+
* @return array|bool|object|null
|
532 |
+
*/
|
533 |
+
public function get_product_filter_query( $feed_id ) {
|
534 |
+
if ( $feed_id ) {
|
535 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feedmeta';
|
536 |
+
|
537 |
+
return $this->_wpdb->get_results( "SELECT meta_value FROM $main_table WHERE product_feed_id = $feed_id AND meta_key = 'product_filter_query'", ARRAY_A );
|
538 |
+
} else {
|
539 |
+
tvc_write_log_file( sprintf( 'Function get_filter_query returned false on feed %s', $feed_id ) );
|
540 |
+
|
541 |
+
return false;
|
542 |
+
}
|
543 |
+
}
|
544 |
+
|
545 |
+
public function get_columns_from_post_table() {
|
546 |
+
return $this->_wpdb->get_results( "SHOW COLUMNS FROM {$this->_table_prefix}posts" );
|
547 |
+
}
|
548 |
+
|
549 |
+
public function get_custom_product_attributes() {
|
550 |
+
$main_table = $this->_table_prefix . 'woocommerce_attribute_taxonomies';
|
551 |
+
|
552 |
+
return $this->_wpdb->get_results( "SELECT attribute_name, attribute_label FROM $main_table" );
|
553 |
+
}
|
554 |
+
|
555 |
+
public function get_custom_product_fields() {
|
556 |
+
$keywords_array = explode( ',', get_option( 'tvc_third_party_attribute_keywords', '%wpmr%,%cpf%,%unit%,%bto%,%yoast%' ) );
|
557 |
+
$main_table = $this->_wpdb->postmeta;
|
558 |
+
|
559 |
+
$query_string = "SELECT DISTINCT meta_key FROM $main_table WHERE meta_key NOT BETWEEN '_' AND '_z'";
|
560 |
+
|
561 |
+
foreach ( $keywords_array as $keyword ) {
|
562 |
+
$query_string .= " OR meta_key LIKE '" . trim( $keyword ) . "'";
|
563 |
+
}
|
564 |
+
|
565 |
+
$query_string .= ' ORDER BY meta_key';
|
566 |
+
|
567 |
+
return $this->_wpdb->get_col( $query_string );
|
568 |
+
}
|
569 |
+
|
570 |
+
public function clear_feed_batch_options() {
|
571 |
+
$this->_wpdb->query( "DELETE FROM {$this->_wpdb->options} WHERE option_name LIKE '%_batch_%'" );
|
572 |
+
}
|
573 |
+
|
574 |
+
/**
|
575 |
+
* @since 2.0.11
|
576 |
+
*/
|
577 |
+
public function clear_feed_batch_sitemeta() {
|
578 |
+
$this->_wpdb->query( "DELETE FROM {$this->_wpdb->sitemeta} WHERE meta_key LIKE '%_batch_%'" );
|
579 |
+
}
|
580 |
+
|
581 |
+
public function get_own_variable_product_attributes( $variable_id ) {
|
582 |
+
$keywords = get_option( 'tvc_third_party_attribute_keywords', '%wpmr%,%cpf%,%unit%,%bto%,%yoast%' );
|
583 |
+
$wpmr_attributes = array();
|
584 |
+
|
585 |
+
if ( $keywords ) {
|
586 |
+
$keywords_array = explode( ',', $keywords );
|
587 |
+
$main_table = $this->_wpdb->postmeta;
|
588 |
+
$query_where_string = count( $keywords_array ) > 0 ? "WHERE (meta_key LIKE '" . trim( $keywords_array[0] ) . "'" : '';
|
589 |
+
|
590 |
+
for ( $i = 1; $i < count( $keywords_array ); $i ++ ) {
|
591 |
+
$query_where_string .= " OR meta_key LIKE '" . trim( $keywords_array[ $i ] ) . "'";
|
592 |
+
}
|
593 |
+
|
594 |
+
$query_where_string .= count( $keywords_array ) > 0 ? ') AND ' : '';
|
595 |
+
|
596 |
+
foreach ( $this->_wpdb->get_results( "SELECT meta_key, meta_value FROM $main_table $query_where_string (post_id = $variable_id)" ) as $key => $row ) {
|
597 |
+
$wpmr_attributes[ $row->meta_key ] = $row->meta_value;
|
598 |
+
}
|
599 |
+
}
|
600 |
+
|
601 |
+
return $wpmr_attributes;
|
602 |
+
}
|
603 |
+
|
604 |
+
public function get_all_product_attributes() {
|
605 |
+
$main_table = $this->_wpdb->postmeta;
|
606 |
+
|
607 |
+
return $this->_wpdb->get_results( "SELECT DISTINCT meta_value FROM $main_table WHERE meta_key = '_product_attributes'" );
|
608 |
+
}
|
609 |
+
|
610 |
+
public function get_current_feed_status( $feed_id ) {
|
611 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
612 |
+
|
613 |
+
return $this->_wpdb->get_results( "SELECT status_id FROM $main_table WHERE product_feed_id = $feed_id" );
|
614 |
+
}
|
615 |
+
|
616 |
+
public function get_country_id( $country_code ) {
|
617 |
+
$main_table = $this->_table_prefix . 'feedmanager_country';
|
618 |
+
|
619 |
+
return $this->_wpdb->get_row( "SELECT country_id FROM $main_table WHERE name_short = '$country_code'" );
|
620 |
+
}
|
621 |
+
|
622 |
+
public function get_feed_ids_with_specific_status( $status_id ) {
|
623 |
+
return $this->_wpdb->get_results( "SELECT product_feed_id FROM {$this->_table_prefix}feedmanager_product_feed WHERE status_id = '$status_id'" );
|
624 |
+
}
|
625 |
+
|
626 |
+
public function switch_feed_status( $feed_id, $new_status ) {
|
627 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
628 |
+
|
629 |
+
return $this->_wpdb->update(
|
630 |
+
$main_table,
|
631 |
+
array(
|
632 |
+
'status_id' => $new_status,
|
633 |
+
'base_status_id' => $new_status,
|
634 |
+
),
|
635 |
+
array( 'product_feed_id' => $feed_id )
|
636 |
+
);
|
637 |
+
}
|
638 |
+
|
639 |
+
public function set_nr_feed_products( $feed_id, $nr_products ) {
|
640 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
641 |
+
|
642 |
+
return $this->_wpdb->update( $main_table, array( 'products' => $nr_products ), array( 'product_feed_id' => $feed_id ) );
|
643 |
+
}
|
644 |
+
|
645 |
+
public function get_nr_feed_products( $feed_id ) {
|
646 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
647 |
+
|
648 |
+
return $this->_wpdb->get_row( "SELECT products FROM $main_table WHERE product_feed_id = '$feed_id'" );
|
649 |
+
}
|
650 |
+
|
651 |
+
/**
|
652 |
+
* Updates a new feed in the product_feed table.
|
653 |
+
*
|
654 |
+
* @param (string) $feed_id
|
655 |
+
* @param (array) $feed_data
|
656 |
+
* @param (array) $data_types
|
657 |
+
*
|
658 |
+
* @return (int|false) nr of affected rows
|
659 |
+
* @since 1.0.0
|
660 |
+
*
|
661 |
+
*/
|
662 |
+
public function update_feed( $feed_id, $feed_data, $data_types ) {
|
663 |
+
|
664 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
665 |
+
|
666 |
+
return $this->_wpdb->update(
|
667 |
+
$main_table,
|
668 |
+
$feed_data,
|
669 |
+
array(
|
670 |
+
'product_feed_id' => $feed_id,
|
671 |
+
),
|
672 |
+
$data_types,
|
673 |
+
array(
|
674 |
+
'%d',
|
675 |
+
)
|
676 |
+
);
|
677 |
+
}
|
678 |
+
|
679 |
+
/**
|
680 |
+
* Update Feed update Meta Data
|
681 |
+
* @param $feed_id
|
682 |
+
* @param $feed_url
|
683 |
+
* @param $nr_products
|
684 |
+
* @return false|int
|
685 |
+
*/
|
686 |
+
public function update_feed_update_data( $feed_id, $feed_url, $nr_products ) {
|
687 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
688 |
+
|
689 |
+
return $this->_wpdb->update(
|
690 |
+
$main_table,
|
691 |
+
array(
|
692 |
+
'updated' => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
|
693 |
+
'url' => $feed_url,
|
694 |
+
'products' => $nr_products,
|
695 |
+
),
|
696 |
+
array( 'product_feed_id' => $feed_id ),
|
697 |
+
array( '%s', '%s', '%s' ),
|
698 |
+
array( '%d' )
|
699 |
+
);
|
700 |
+
}
|
701 |
+
|
702 |
+
/**
|
703 |
+
* @param $feed_id
|
704 |
+
* @return mixed
|
705 |
+
*/
|
706 |
+
public function get_file_url_from_feed( $feed_id ) {
|
707 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
708 |
+
$result = $this->_wpdb->get_row( "SELECT url FROM $main_table WHERE product_feed_id = $feed_id", ARRAY_A );
|
709 |
+
|
710 |
+
return $result['url'];
|
711 |
+
}
|
712 |
+
|
713 |
+
/**
|
714 |
+
* Sets the status id of a feed
|
715 |
+
*
|
716 |
+
* @param string $feed_id
|
717 |
+
* @param int $status
|
718 |
+
*
|
719 |
+
* @return bool
|
720 |
+
*/
|
721 |
+
public function update_feed_file_status( $feed_id, $status ) {
|
722 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
723 |
+
|
724 |
+
return $this->_wpdb->update( $main_table, array( 'status_id' => $status ), array( 'product_feed_id' => $feed_id ), array( '%d' ), array( '%d' ) );
|
725 |
+
}
|
726 |
+
|
727 |
+
/**
|
728 |
+
* @param $feed_id
|
729 |
+
* @param $meta_data
|
730 |
+
* @return false|int
|
731 |
+
*/
|
732 |
+
public function update_meta_data( $feed_id, $meta_data ) {
|
733 |
+
// TODO: Onderstaande proces is nog niet echt efficient. In plaats van het standaard verwijderen
|
734 |
+
// van elke bestaande regel met het geselecteerde id nummer, zou ik eerst moeten kijken of
|
735 |
+
// deze regel wel is gewijzigd. Indien een regel niet is gewijzigd zou ik hem ook niet moeten
|
736 |
+
// verwijderen.
|
737 |
+
|
738 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feedmeta';
|
739 |
+
|
740 |
+
// first remove all meta data belonging to this feed except the product_filter_query
|
741 |
+
//$this->_wpdb->delete( $main_data, array( 'product_feed_id' => $feed_id ) ); // could not use it because it can't work with !=
|
742 |
+
$this->_wpdb->query( "DELETE FROM $main_table WHERE product_feed_id = $feed_id AND meta_key != 'product_filter_query'" );
|
743 |
+
|
744 |
+
$counter = 0;
|
745 |
+
|
746 |
+
for ( $i = 0; $i < count( $meta_data ); $i ++ ) {
|
747 |
+
if ( ! empty( $meta_data[ $i ]->value ) && '{}' !== $meta_data[ $i ]->value ) {
|
748 |
+
$result = $this->_wpdb->insert(
|
749 |
+
$main_table,
|
750 |
+
array(
|
751 |
+
'product_feed_id' => $feed_id,
|
752 |
+
'meta_key' => $meta_data[ $i ]->key,
|
753 |
+
'meta_value' => $meta_data[ $i ]->value,
|
754 |
+
),
|
755 |
+
array(
|
756 |
+
'%d',
|
757 |
+
'%s',
|
758 |
+
'%s',
|
759 |
+
)
|
760 |
+
);
|
761 |
+
|
762 |
+
$counter += $result;
|
763 |
+
}
|
764 |
+
}
|
765 |
+
|
766 |
+
return $counter;
|
767 |
+
}
|
768 |
+
|
769 |
+
/**
|
770 |
+
* Resets the status_id's of failed feeds.
|
771 |
+
*
|
772 |
+
* @since 2.7.0
|
773 |
+
*/
|
774 |
+
public function reset_all_feed_status() {
|
775 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
776 |
+
$failed_ids = $this->_wpdb->get_results( "SELECT product_feed_id FROM $main_table WHERE status_id > '2' OR status_id = '0'", 'ARRAY_A' );
|
777 |
+
|
778 |
+
foreach ( $failed_ids as $feed_id ) {
|
779 |
+
$id = $feed_id['product_feed_id'];
|
780 |
+
$base_status = $this->_wpdb->get_var( "SELECT base_status_id FROM $main_table WHERE product_feed_id = '$id'" );
|
781 |
+
$new_status = '1' === $base_status || '2' === $base_status ? $base_status : '2';
|
782 |
+
|
783 |
+
$this->_wpdb->update(
|
784 |
+
$main_table,
|
785 |
+
array(
|
786 |
+
'status_id' => $new_status,
|
787 |
+
'products' => 0,
|
788 |
+
),
|
789 |
+
array(
|
790 |
+
'product_feed_id' => $id,
|
791 |
+
),
|
792 |
+
array(
|
793 |
+
'%s',
|
794 |
+
'%d',
|
795 |
+
)
|
796 |
+
);
|
797 |
+
}
|
798 |
+
}
|
799 |
+
|
800 |
+
public function store_feed_filter( $feed_id, $filter ) {
|
801 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feedmeta';
|
802 |
+
|
803 |
+
if ( $filter ) {
|
804 |
+
$exists = $this->_wpdb->get_results( "SELECT meta_id FROM $main_table WHERE product_feed_id = $feed_id AND meta_key = 'product_filter_query'" );
|
805 |
+
|
806 |
+
if ( $exists ) {
|
807 |
+
$this->_wpdb->update(
|
808 |
+
$main_table,
|
809 |
+
array(
|
810 |
+
'meta_value' => $filter,
|
811 |
+
),
|
812 |
+
array(
|
813 |
+
'product_feed_id' => $feed_id,
|
814 |
+
'meta_key' => 'product_filter_query',
|
815 |
+
),
|
816 |
+
array(
|
817 |
+
'%s',
|
818 |
+
),
|
819 |
+
array(
|
820 |
+
'%d',
|
821 |
+
'%s',
|
822 |
+
)
|
823 |
+
);
|
824 |
+
} else {
|
825 |
+
$this->_wpdb->insert(
|
826 |
+
$main_table,
|
827 |
+
array(
|
828 |
+
'product_feed_id' => $feed_id,
|
829 |
+
'meta_key' => 'product_filter_query',
|
830 |
+
'meta_value' => $filter,
|
831 |
+
),
|
832 |
+
array(
|
833 |
+
'%d',
|
834 |
+
'%s',
|
835 |
+
'%s',
|
836 |
+
)
|
837 |
+
);
|
838 |
+
}
|
839 |
+
} else {
|
840 |
+
$this->_wpdb->query( "DELETE FROM $main_table WHERE product_feed_id = $feed_id AND meta_key = 'product_filter_query'" );
|
841 |
+
}
|
842 |
+
}
|
843 |
+
|
844 |
+
public function insert_meta_data( $feed_id, $meta_data, $feed_filter_data, $category_mapping ) {
|
845 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feedmeta';
|
846 |
+
|
847 |
+
$counter = 0;
|
848 |
+
|
849 |
+
for ( $i = 0; $i < count( $meta_data ); $i ++ ) {
|
850 |
+
$result = $this->_wpdb->insert(
|
851 |
+
$main_table,
|
852 |
+
array(
|
853 |
+
'product_feed_id' => $feed_id,
|
854 |
+
'meta_key' => $meta_data[ $i ]['meta_key'],
|
855 |
+
'meta_value' => $meta_data[ $i ]['meta_value'],
|
856 |
+
),
|
857 |
+
array(
|
858 |
+
'%d',
|
859 |
+
'%s',
|
860 |
+
'%s',
|
861 |
+
)
|
862 |
+
);
|
863 |
+
|
864 |
+
$counter += $result;
|
865 |
+
}
|
866 |
+
|
867 |
+
for ( $i = 0; $i < count( $feed_filter_data ); $i++ ) {
|
868 |
+
$this->store_feed_filter( $feed_id, $feed_filter_data[ $i ]['meta_value'] );
|
869 |
+
}
|
870 |
+
|
871 |
+
$counter += $this->_wpdb->insert(
|
872 |
+
$main_table,
|
873 |
+
array(
|
874 |
+
'product_feed_id' => $feed_id,
|
875 |
+
'meta_key' => 'category_mapping',
|
876 |
+
'meta_value' => $category_mapping[0]['meta_value'],
|
877 |
+
),
|
878 |
+
array(
|
879 |
+
'%d',
|
880 |
+
'%s',
|
881 |
+
'%s',
|
882 |
+
)
|
883 |
+
);
|
884 |
+
|
885 |
+
return $counter;
|
886 |
+
}
|
887 |
+
|
888 |
+
public function title_exists( $feed_title ) {
|
889 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
890 |
+
$count = $this->_wpdb->get_var( "SELECT COUNT(*) FROM $main_table WHERE title = '$feed_title'" );
|
891 |
+
|
892 |
+
return $count > 0 ? true : false;
|
893 |
+
}
|
894 |
+
|
895 |
+
/**
|
896 |
+
* Inserts a new feed in the product_feed table and returns its new id.
|
897 |
+
*
|
898 |
+
* @param array $feed_data_to_store
|
899 |
+
* @param array $feed_types
|
900 |
+
*
|
901 |
+
* @return integer containing the id of the new feed
|
902 |
+
* @since 1.0.0
|
903 |
+
*
|
904 |
+
*/
|
905 |
+
public function create_feed( $feed_data_to_store, $feed_types ) {
|
906 |
+
|
907 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
908 |
+
|
909 |
+
$this->_wpdb->insert(
|
910 |
+
$main_table,
|
911 |
+
$feed_data_to_store,
|
912 |
+
$feed_types
|
913 |
+
);
|
914 |
+
|
915 |
+
return $this->_wpdb->insert_id;
|
916 |
+
}
|
917 |
+
|
918 |
+
public function getCountryID($feed_id){
|
919 |
+
$countryID = $this->_wpdb->get_results("SELECT country_id FROM {$this->_table_prefix}feedmanager_product_feed WHERE product_feed_id = ".$feed_id);
|
920 |
+
|
921 |
+
return $countryID;
|
922 |
+
}
|
923 |
+
|
924 |
+
public function getScheduleTime($feed_id){
|
925 |
+
$scheduleTime = $this->_wpdb->get_results("SELECT schedule FROM {$this->_table_prefix}feedmanager_product_feed WHERE product_feed_id = ".$feed_id);
|
926 |
+
|
927 |
+
return $scheduleTime;
|
928 |
+
}
|
929 |
+
|
930 |
+
public function getFeedData($feed_id){
|
931 |
+
$feedData = $this->_wpdb->get_results("SELECT title,feed_description,feed_title FROM {$this->_table_prefix}feedmanager_product_feed WHERE product_feed_id = ".$feed_id);
|
932 |
+
|
933 |
+
return $feedData;
|
934 |
+
}
|
935 |
+
|
936 |
+
public function getCountryCode($countryID){
|
937 |
+
$countryCode = $this->_wpdb->get_results("SELECT name_short FROM {$this->_table_prefix}feedmanager_country WHERE country_id =".$countryID[0]->country_id);
|
938 |
+
return $countryCode;
|
939 |
+
}
|
940 |
+
|
941 |
+
public function insertGmcFeedId($feedID,$feed_id){
|
942 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
943 |
+
return $this->_wpdb->update( $main_table, array( 'gmc_feed_id' => $feedID ), array( 'product_feed_id' => $feed_id ) );
|
944 |
+
}
|
945 |
+
|
946 |
+
public function getGmcFeedId($feed_id){
|
947 |
+
$gmcFeedId = $this->_wpdb->get_results("SELECT gmc_feed_id FROM {$this->_table_prefix}feedmanager_product_feed WHERE product_feed_id =". $feed_id);
|
948 |
+
return $gmcFeedId;
|
949 |
+
}
|
950 |
+
|
951 |
+
public function getFeedURL($feed_id){
|
952 |
+
$main_table = $this->_table_prefix . 'feedmanager_product_feed';
|
953 |
+
return $this->_wpdb->get_results("SELECT url,feed_title,status_id FROM $main_table WHERE product_feed_id =". $feed_id);
|
954 |
+
}
|
955 |
+
|
956 |
+
public function getTableColumns($table) {
|
957 |
+
return $this->_wpdb->get_results("SELECT column_name as field FROM information_schema.columns WHERE table_name = '$table'");
|
958 |
+
}
|
959 |
+
|
960 |
+
public function getTableData($table = 'wp_postmeta', $columns = array()) {
|
961 |
+
return $this->_wpdb->get_results("SELECT DISTINCT " . implode(',', $columns) . " as field FROM $table");
|
962 |
+
}
|
963 |
+
|
964 |
+
public function getTablePostMeta($post_id) {
|
965 |
+
return $this->_wpdb->get_results("SELECT meta_key,meta_value FROM wp_postmeta where post_id=" . $post_id);
|
966 |
+
}
|
967 |
+
}
|
968 |
+
// End of TVC_Queries class
|
969 |
+
|
970 |
+
endif;
|
includes/data/class-tvc-tab.php
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Tab Class.
|
5 |
+
*
|
6 |
+
* @package TVC Product Feed Manager/Data/Classes
|
7 |
+
* @version 1.0.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Tab' ) ) :
|
15 |
+
|
16 |
+
class TVC_Tab {
|
17 |
+
|
18 |
+
/*
|
19 |
+
* Contains the page identifier string
|
20 |
+
*/
|
21 |
+
private $_page_identifier;
|
22 |
+
|
23 |
+
/*
|
24 |
+
* Is the selected tab or not
|
25 |
+
*/
|
26 |
+
private $_tab_status;
|
27 |
+
|
28 |
+
/*
|
29 |
+
* Contains the title of the tab
|
30 |
+
*/
|
31 |
+
private $_tab_title;
|
32 |
+
|
33 |
+
/*
|
34 |
+
* Contains a class identifier
|
35 |
+
*/
|
36 |
+
private $_class_identifier;
|
37 |
+
|
38 |
+
/**
|
39 |
+
* TVC_Tab constructor.
|
40 |
+
*
|
41 |
+
* @param string $page_identifier
|
42 |
+
* @param bool $tab_status
|
43 |
+
* @param string $tab_title
|
44 |
+
* @param string $class_identifier
|
45 |
+
*/
|
46 |
+
public function __construct( $page_identifier, $tab_status, $tab_title, $class_identifier ) {
|
47 |
+
|
48 |
+
$this->_page_identifier = $page_identifier;
|
49 |
+
$this->_tab_status = $tab_status;
|
50 |
+
$this->_tab_title = $tab_title;
|
51 |
+
$this->_class_identifier = $class_identifier;
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Returns the tabs url parameters page and tab
|
56 |
+
*
|
57 |
+
* @return string
|
58 |
+
*/
|
59 |
+
public function get_page_tab_url() {
|
60 |
+
return 'page=tvc-product-feed-manager&tab=' . $this->_page_identifier;
|
61 |
+
}
|
62 |
+
|
63 |
+
public function get_page_identifier() {
|
64 |
+
return $this->_page_identifier;
|
65 |
+
}
|
66 |
+
|
67 |
+
public function get_class_identifier() {
|
68 |
+
return $this->_class_identifier;
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Returns a string that can be used in the tabs html code to identify it as the active tab
|
73 |
+
*
|
74 |
+
* @return string
|
75 |
+
*/
|
76 |
+
public function tab_selected_string() {
|
77 |
+
return $this->_tab_status ? ' nav-tab-active' : '';
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Returns the tab title
|
82 |
+
*
|
83 |
+
* @return string
|
84 |
+
*/
|
85 |
+
public function get_tab_title() {
|
86 |
+
return $this->_tab_title;
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* Returns the main input wrapper class name
|
91 |
+
*
|
92 |
+
* @return string
|
93 |
+
*/
|
94 |
+
public function get_main_input_wrapper_class() {
|
95 |
+
return 'TVC_' . $this->_class_identifier . '_Main_Input_Wrapper';
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Returns the category selector wrapper class name
|
100 |
+
*
|
101 |
+
* @return string
|
102 |
+
*/
|
103 |
+
public function get_category_selector_wrapper_class() {
|
104 |
+
return 'TVC_' . $this->_class_identifier . '_Category_Wrapper';
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Returns the attribute mapping wrapper class name
|
109 |
+
*
|
110 |
+
* @return string
|
111 |
+
*/
|
112 |
+
public function get_attribute_mapping_wrapper_class() {
|
113 |
+
return 'TVC_' . $this->_class_identifier . '_Attribute_Mapping_Wrapper';
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Set this tab as the selected tab
|
118 |
+
*/
|
119 |
+
public function set_tab_as_selected() {
|
120 |
+
$this->_tab_status = true;
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
124 |
+
// end of TVC_Tab class
|
125 |
+
|
126 |
+
endif;
|
includes/data/class-tvc-taxonomies.php
ADDED
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Taxonomies Class.
|
5 |
+
*
|
6 |
+
* @package TVC Product Feed Manager/Data/Classes
|
7 |
+
* @version 5.2.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Taxonomies' ) ) :
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Taxonomies Class
|
18 |
+
*/
|
19 |
+
class TVC_Taxonomies {
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Generates a string of shop taxonomies (like a category string) in the correct order
|
23 |
+
*
|
24 |
+
* @param string $product_id
|
25 |
+
* @param string $tax
|
26 |
+
* @param string $separator
|
27 |
+
*
|
28 |
+
* @return string
|
29 |
+
*/
|
30 |
+
public static function make_shop_taxonomies_string( $product_id, $tax = 'product_cat', $separator = ' > ' ) {
|
31 |
+
$args = array(
|
32 |
+
'taxonomy' => $tax,
|
33 |
+
'orderby' => 'parent',
|
34 |
+
'order' => 'DESC',
|
35 |
+
);
|
36 |
+
|
37 |
+
// get the post term ordered with the last child cat first
|
38 |
+
$cats = wp_get_post_terms( $product_id, $tax, $args );
|
39 |
+
|
40 |
+
$result = array();
|
41 |
+
|
42 |
+
if ( count( $cats ) === 0 ) {
|
43 |
+
return '';
|
44 |
+
}
|
45 |
+
|
46 |
+
// anonymous function to get the correct taxonomy string
|
47 |
+
$cat_string = function ( $id ) use ( &$result, &$cat_string, $tax ) {
|
48 |
+
// get the first term
|
49 |
+
$term = get_term_by( 'id', $id, $tax, 'ARRAY_A' );
|
50 |
+
|
51 |
+
// check if the term has a parent
|
52 |
+
if ( $term['parent'] ) {
|
53 |
+
// start the anonymous function again with the parent id
|
54 |
+
$cat_string( $term['parent'] );
|
55 |
+
}
|
56 |
+
|
57 |
+
// add the terms name to the result
|
58 |
+
$result[] = $term['name'];
|
59 |
+
};
|
60 |
+
|
61 |
+
// activate the anonymous function with the first categories term_id
|
62 |
+
$cat_string( $cats[0]->term_id );
|
63 |
+
|
64 |
+
return implode( $separator, $result );
|
65 |
+
}
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Generates a string with all selected categories
|
69 |
+
*
|
70 |
+
* @param string $post_id
|
71 |
+
* @param string $separator
|
72 |
+
*
|
73 |
+
* @return string
|
74 |
+
*/
|
75 |
+
public static function get_shop_categories( $post_id, $separator = ', ' ) {
|
76 |
+
$return_string = '';
|
77 |
+
|
78 |
+
$args = array(
|
79 |
+
'taxonomy' => 'product_cat',
|
80 |
+
'orderby' => 'term_id',
|
81 |
+
);
|
82 |
+
|
83 |
+
$cats = wp_get_post_terms( $post_id, 'product_cat', $args );
|
84 |
+
|
85 |
+
foreach ( $cats as $cat ) {
|
86 |
+
$return_string .= $cat->name . $separator;
|
87 |
+
}
|
88 |
+
|
89 |
+
return rtrim( $return_string, $separator );
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Returns the product category that is selected as primary (only when Yoast plugin is installed)
|
94 |
+
*
|
95 |
+
* @param string $id
|
96 |
+
*
|
97 |
+
* @return bool
|
98 |
+
*/
|
99 |
+
public static function get_yoast_primary_cat( $id ) {
|
100 |
+
if ( ! is_plugin_active( 'wordpress-seo/wp-seo.php' ) && ! is_plugin_active_for_network( 'wordpress-seo/wp-seo.php' )
|
101 |
+
&& ! is_plugin_active( 'wordpress-seo-premium/wp-seo-premium.php' ) && ! is_plugin_active_for_network( 'wordpress-seo-premium/wp-seo-premium.php' ) ) {
|
102 |
+
return false; // return false if yoast plugin is inactive
|
103 |
+
}
|
104 |
+
|
105 |
+
$primary_cat_id = get_post_meta( $id, '_yoast_wpseo_primary_product_cat', true );
|
106 |
+
|
107 |
+
if ( $primary_cat_id ) {
|
108 |
+
$product_cat[0] = get_term( $primary_cat_id, 'product_cat' );
|
109 |
+
if ( isset( $product_cat[0]->term_id ) ) {
|
110 |
+
return $product_cat;
|
111 |
+
}
|
112 |
+
} else {
|
113 |
+
return false;
|
114 |
+
}
|
115 |
+
|
116 |
+
return false;
|
117 |
+
}
|
118 |
+
|
119 |
+
public static function get_shop_categories_list() {
|
120 |
+
$args = array(
|
121 |
+
'hide_empty' => 0,
|
122 |
+
'taxonomy' => 'product_cat',
|
123 |
+
'hierarchical' => 1,
|
124 |
+
'orderby' => 'name',
|
125 |
+
'order' => 'ASC',
|
126 |
+
'exclude' => apply_filters( 'tvc_category_mapping_exclude', array() ),
|
127 |
+
'exclude_tree' => apply_filters( 'tvc_category_mapping_exclude_tree', array() ),
|
128 |
+
'number' => absint( apply_filters( 'tvc_category_mapping_max_categories', 0 ) ),
|
129 |
+
'child_of' => 0,
|
130 |
+
);
|
131 |
+
|
132 |
+
$args = apply_filters( 'tvc_category_mapping_args', $args );
|
133 |
+
|
134 |
+
return self::get_cat_hierarchy( 0, $args );
|
135 |
+
}
|
136 |
+
|
137 |
+
private static function get_cat_hierarchy( $parent, $args ) {
|
138 |
+
$cats = get_categories( $args );
|
139 |
+
$ret = new stdClass;
|
140 |
+
|
141 |
+
foreach ( $cats as $cat ) {
|
142 |
+
if ( $cat->parent == $parent ) {
|
143 |
+
$id = $cat->cat_ID;
|
144 |
+
$ret->$id = $cat;
|
145 |
+
$ret->$id->children = self::get_cat_hierarchy( $id, $args );
|
146 |
+
}
|
147 |
+
}
|
148 |
+
return $ret;
|
149 |
+
}
|
150 |
+
}
|
151 |
+
// end of TVC_Taxonomies_Class
|
152 |
+
|
153 |
+
endif;
|
includes/data/class-tvc-variations.php
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TVC Product Feed Manager Variations Class.
|
5 |
+
*
|
6 |
+
* @package TVC Product Feed Manager/Data/Classes
|
7 |
+
* @version 1.9.0
|
8 |
+
*/
|
9 |
+
|
10 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
11 |
+
exit;
|
12 |
+
}
|
13 |
+
|
14 |
+
if ( ! class_exists( 'TVC_Variations' ) ) :
|
15 |
+
|
16 |
+
/**
|
17 |
+
* Variations Class
|
18 |
+
*/
|
19 |
+
class TVC_Variations {
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Fills the product attributes with the correct variation data
|
23 |
+
*
|
24 |
+
* @param array $product_data
|
25 |
+
* @param WC_Product_Variation $woocommerce_variation_data
|
26 |
+
* @param array $wpmr_variation_data
|
27 |
+
* @param string $feed_language
|
28 |
+
*/
|
29 |
+
public static function fill_product_data_with_variation_data( &$product_data, $woocommerce_variation_data, $wpmr_variation_data, $feed_language ) {
|
30 |
+
$permalink = array_key_exists( 'permalink', $product_data ) ? $product_data['permalink'] : ''; // some channels don't require permalinks
|
31 |
+
$conversions = self::variation_conversion_table( $woocommerce_variation_data, $permalink, $feed_language );
|
32 |
+
|
33 |
+
$variation_attributes = $woocommerce_variation_data->get_variation_attributes();
|
34 |
+
|
35 |
+
foreach ( $product_data as $key => $field_value ) {
|
36 |
+
if ( in_array( $key, array_keys( $conversions ) ) && $field_value !== $conversions[ $key ] && $conversions[ $key ] ) {
|
37 |
+
$product_data[ $key ] = $conversions[ $key ];
|
38 |
+
}
|
39 |
+
|
40 |
+
if ( array_key_exists( $key, $variation_attributes ) && $variation_attributes[ $key ] ) {
|
41 |
+
$slug_value = $variation_attributes[ $key ];
|
42 |
+
$product_data[ $key ] = get_term_by( 'slug', $slug_value, ltrim( $key, 'attribute_' ) )->name;
|
43 |
+
continue;
|
44 |
+
}
|
45 |
+
|
46 |
+
if ( array_key_exists( 'attribute_pa_' . $key, $variation_attributes ) && $variation_attributes[ 'attribute_pa_' . $key ] ) {
|
47 |
+
$slug_value = $variation_attributes[ 'attribute_pa_' . $key ];
|
48 |
+
$product_data[ $key ] = get_term_by( 'slug', $slug_value, 'pa_' . $key )->name;
|
49 |
+
continue;
|
50 |
+
}
|
51 |
+
|
52 |
+
if ( $wpmr_variation_data && array_key_exists( $key, $wpmr_variation_data ) ) {
|
53 |
+
$product_data[ $key ] = $wpmr_variation_data[ $key ];
|
54 |
+
}
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
private static function variation_conversion_table( $variation_data, $main_permalink, $feed_language ) {
|
59 |
+
return array(
|
60 |
+
'ID' => (string) $variation_data->get_id(),
|
61 |
+
'_downloadable' => $variation_data->get_downloadable( 'feed' ),
|
62 |
+
'_virtual' => $variation_data->get_virtual( 'feed' ),
|
63 |
+
'_manage_stock' => $variation_data->get_manage_stock( 'feed' ),
|
64 |
+
'_stock' => $variation_data->get_stock_quantity( 'feed' ),
|
65 |
+
'_backorders' => $variation_data->get_backorders( 'feed' ),
|
66 |
+
'_stock_status' => $variation_data->get_stock_status( 'feed' ),
|
67 |
+
'_sku' => $variation_data->get_sku( 'feed' ),
|
68 |
+
'_weight' => $variation_data->get_weight( 'feed' ),
|
69 |
+
'_length' => $variation_data->get_length( 'feed' ),
|
70 |
+
'_width' => $variation_data->get_width( 'feed' ),
|
71 |
+
'_height' => $variation_data->get_height( 'feed' ),
|
72 |
+
'post_content' => $variation_data->get_description( 'feed' ),
|
73 |
+
'_regular_price' => tvc_prep_money_values( $variation_data->get_regular_price( 'feed' ), $feed_language ),
|
74 |
+
'_sale_price' => tvc_prep_money_values( $variation_data->get_sale_price( 'feed' ), $feed_language ),
|
75 |
+
'_sale_price_dates_from' => $variation_data->get_date_on_sale_from( 'feed' ) && ( $date = $variation_data->get_date_on_sale_from( 'feed' )->getTimestamp() ) ? tvc_convert_price_date_to_feed_format( $date ) : '',
|
76 |
+
'_sale_price_dates_to' => $variation_data->get_date_on_sale_to( 'feed' ) && ( $date = $variation_data->get_date_on_sale_to( 'feed' )->getTimestamp() ) ? tvc_convert_price_date_to_feed_format( $date ) : '',
|
77 |
+
'attachment_url' => wp_get_attachment_url( get_post_thumbnail_id( $variation_data->get_id() ) ),
|
78 |
+
'permalink' => $main_permalink,
|
79 |
+
);
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
// End of TVC_Variations_Class
|
84 |
+
|
85 |
+
endif;
|
includes/data/js/tvc_ajaxdatahandling.js
ADDED
@@ -0,0 +1,718 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"use strict";
|
2 |
+
var myAjaxNonces;
|
3 |
+
|
4 |
+
function tvc_getFeedList( callback ) {
|
5 |
+
|
6 |
+
jQuery.post(
|
7 |
+
myAjaxNonces.ajaxurl,
|
8 |
+
{
|
9 |
+
action: 'tvcajax-get-list-of-feeds',
|
10 |
+
postFeedsListNonce: myAjaxNonces.postFeedsListNonce,
|
11 |
+
|
12 |
+
},
|
13 |
+
function( response ) {
|
14 |
+
|
15 |
+
callback( tvc_validateResponse( response ) );
|
16 |
+
}
|
17 |
+
);
|
18 |
+
}
|
19 |
+
|
20 |
+
function tvc_getBackupsList( callback ) {
|
21 |
+
jQuery.post(
|
22 |
+
myAjaxNonces.ajaxurl,
|
23 |
+
{
|
24 |
+
action: 'tvcajax-get-list-of-backups',
|
25 |
+
postBackupListNonce: myAjaxNonces.postBackupListNonce,
|
26 |
+
|
27 |
+
},
|
28 |
+
function( response ) {
|
29 |
+
|
30 |
+
callback( tvc_validateResponse( response ) );
|
31 |
+
}
|
32 |
+
);
|
33 |
+
}
|
34 |
+
|
35 |
+
function tvc_getSettingsOptions( callback ) {
|
36 |
+
|
37 |
+
jQuery.post(
|
38 |
+
myAjaxNonces.ajaxurl,
|
39 |
+
{
|
40 |
+
action: 'tvcajax-get-settings-options',
|
41 |
+
postSetupOptionsNonce: myAjaxNonces.postSetupOptionsNonce,
|
42 |
+
|
43 |
+
},
|
44 |
+
function( response ) {
|
45 |
+
|
46 |
+
callback( tvc_validateResponse( response ) );
|
47 |
+
}
|
48 |
+
);
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Reads and returns all possible output fields from the selected merchant
|
53 |
+
*
|
54 |
+
* @param {int} feedId
|
55 |
+
* @param {int} channelId
|
56 |
+
* @param callback
|
57 |
+
* @returns list with output fields
|
58 |
+
*/
|
59 |
+
function tvc_getOutputFields( feedId, channelId, callback ) {
|
60 |
+
|
61 |
+
jQuery.post(
|
62 |
+
myAjaxNonces.ajaxurl,
|
63 |
+
{
|
64 |
+
action: 'tvcajax-get-output-fields',
|
65 |
+
feedId: feedId,
|
66 |
+
channelId: channelId,
|
67 |
+
outputFieldsNonce: myAjaxNonces.outputFieldsNonce,
|
68 |
+
|
69 |
+
},
|
70 |
+
function( response ) {
|
71 |
+
|
72 |
+
callback( tvc_validateResponse( response ) );
|
73 |
+
}
|
74 |
+
);
|
75 |
+
}
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Reads and returns all possible source fields from the selected source
|
79 |
+
*
|
80 |
+
* @param {int} sourceId
|
81 |
+
* @param callback
|
82 |
+
* @returns list with input fields
|
83 |
+
*/
|
84 |
+
function tvc_getSourceFields( sourceId, callback ) {
|
85 |
+
|
86 |
+
jQuery.post(
|
87 |
+
myAjaxNonces.ajaxurl,
|
88 |
+
{
|
89 |
+
action: 'tvcajax-get-input-fields',
|
90 |
+
sourceId: sourceId,
|
91 |
+
inputFieldsNonce: myAjaxNonces.inputFieldsNonce,
|
92 |
+
|
93 |
+
},
|
94 |
+
function( response ) {
|
95 |
+
|
96 |
+
callback( tvc_validateResponse( response ) );
|
97 |
+
}
|
98 |
+
);
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Get main feed filters
|
103 |
+
* @param feedId
|
104 |
+
* @param callback
|
105 |
+
*/
|
106 |
+
function tvc_getMainFeedFilters( feedId, callback ) {
|
107 |
+
|
108 |
+
jQuery.post(
|
109 |
+
myAjaxNonces.ajaxurl,
|
110 |
+
{
|
111 |
+
action: 'tvcajax-get-main-feed-filters',
|
112 |
+
feedId: feedId,
|
113 |
+
inputFeedFiltersNonce: myAjaxNonces.inputFeedFiltersNonce,
|
114 |
+
|
115 |
+
},
|
116 |
+
function( response ) {
|
117 |
+
|
118 |
+
callback( tvc_validateResponse( response ) );
|
119 |
+
}
|
120 |
+
);
|
121 |
+
}
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Fetch next category
|
125 |
+
* @param channelId
|
126 |
+
* @param requestedLevel
|
127 |
+
* @param parentCategory
|
128 |
+
* @param language
|
129 |
+
* @param callback
|
130 |
+
*/
|
131 |
+
function tvc_getNextCategories( channelId, requestedLevel, parentCategory, language, callback ) {
|
132 |
+
|
133 |
+
jQuery.post(
|
134 |
+
myAjaxNonces.ajaxurl,
|
135 |
+
{
|
136 |
+
action: 'tvcajax-get-next-categories',
|
137 |
+
channelId: channelId,
|
138 |
+
requestedLevel: requestedLevel,
|
139 |
+
parentCategory: parentCategory,
|
140 |
+
fileLanguage: language,
|
141 |
+
nextCategoryNonce: myAjaxNonces.nextCategoryNonce,
|
142 |
+
|
143 |
+
},
|
144 |
+
function( response ) {
|
145 |
+
|
146 |
+
response = response.trim();
|
147 |
+
|
148 |
+
if ( response.substr( response.length - 1 ) === '0' ) {
|
149 |
+
response = response.substring( 0, response.length - 1 );
|
150 |
+
}
|
151 |
+
|
152 |
+
callback( tvc_validateResponse( response ) );
|
153 |
+
}
|
154 |
+
);
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Get Category Listing from String
|
159 |
+
* @param channelId
|
160 |
+
* @param mainCategoriesString
|
161 |
+
* @param language
|
162 |
+
* @param callback
|
163 |
+
*/
|
164 |
+
function tvc_getCategoryListsFromString( channelId, mainCategoriesString, language, callback ) {
|
165 |
+
jQuery.post(
|
166 |
+
myAjaxNonces.ajaxurl,
|
167 |
+
{
|
168 |
+
action: 'tvcajax-get-category-lists',
|
169 |
+
channelId: channelId,
|
170 |
+
mainCategories: mainCategoriesString,
|
171 |
+
fileLanguage: language,
|
172 |
+
categoryListsNonce: myAjaxNonces.categoryListsNonce,
|
173 |
+
|
174 |
+
},
|
175 |
+
function( response ) {
|
176 |
+
|
177 |
+
callback( tvc_validateResponse( response ) );
|
178 |
+
}
|
179 |
+
);
|
180 |
+
}
|
181 |
+
|
182 |
+
/**
|
183 |
+
* Ajax Call for update feed to database
|
184 |
+
* @param feedData
|
185 |
+
* @param metaData
|
186 |
+
* @param feedFilter
|
187 |
+
* @param callback
|
188 |
+
*/
|
189 |
+
function tvc_updateFeedToDb( feedData, metaData, feedFilter, callback ) {
|
190 |
+
jQuery.post(
|
191 |
+
myAjaxNonces.ajaxurl,
|
192 |
+
{
|
193 |
+
action: 'tvcajax-update-feed-data',
|
194 |
+
feed: JSON.stringify( feedData ),
|
195 |
+
feedFilter: feedFilter ? feedFilter[ 0 ][ 'meta_value' ] : '',
|
196 |
+
metaData: JSON.stringify( metaData ),
|
197 |
+
updateFeedDataNonce: myAjaxNonces.updateFeedDataNonce,
|
198 |
+
},
|
199 |
+
function( response ) {
|
200 |
+
console.log(response);
|
201 |
+
callback( tvc_validateResponse( response ) );
|
202 |
+
}
|
203 |
+
);
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* Ajax call for update XML feed file
|
208 |
+
* @param feed_id
|
209 |
+
* @param callback
|
210 |
+
*/
|
211 |
+
function tvc_updateFeedFile( feed_id, callback ) {
|
212 |
+
jQuery.post(
|
213 |
+
myAjaxNonces.ajaxurl,
|
214 |
+
{
|
215 |
+
action: 'tvcajax-update-feed-file',
|
216 |
+
dataType: 'text',
|
217 |
+
feedId: feed_id,
|
218 |
+
updateFeedFileNonce: myAjaxNonces.updateFeedFileNonce,
|
219 |
+
|
220 |
+
},
|
221 |
+
function( response ) {
|
222 |
+
|
223 |
+
callback( tvc_validateResponse( response ) );
|
224 |
+
}
|
225 |
+
);
|
226 |
+
}
|
227 |
+
|
228 |
+
/**
|
229 |
+
* Update current/selected feed status
|
230 |
+
* @param feedId
|
231 |
+
* @param callback
|
232 |
+
*/
|
233 |
+
function tvc_getCurrentFeedStatus( feedId, callback ) {
|
234 |
+
|
235 |
+
jQuery.post(
|
236 |
+
myAjaxNonces.ajaxurl,
|
237 |
+
{
|
238 |
+
action: 'tvcajax-get-feed-status',
|
239 |
+
sourceId: feedId,
|
240 |
+
feedStatusNonce: myAjaxNonces.feedStatusNonce,
|
241 |
+
|
242 |
+
},
|
243 |
+
function( response ) {
|
244 |
+
|
245 |
+
callback( tvc_validateResponse( response ) );
|
246 |
+
}
|
247 |
+
);
|
248 |
+
}
|
249 |
+
|
250 |
+
function tvc_getFeedData( feedId, callback ) {
|
251 |
+
|
252 |
+
jQuery.post(
|
253 |
+
myAjaxNonces.ajaxurl,
|
254 |
+
{
|
255 |
+
action: 'tvcajax-get-feed-data',
|
256 |
+
sourceId: feedId,
|
257 |
+
feedDataNonce: myAjaxNonces.feedDataNonce,
|
258 |
+
|
259 |
+
},
|
260 |
+
function( response ) {
|
261 |
+
|
262 |
+
callback( tvc_validateResponse( response ) );
|
263 |
+
}
|
264 |
+
);
|
265 |
+
}
|
266 |
+
|
267 |
+
/**
|
268 |
+
* Switch feed status auto/manual
|
269 |
+
* @param feedId
|
270 |
+
* @param callback
|
271 |
+
*/
|
272 |
+
function tvc_switchFeedStatus( feedId, callback ) {
|
273 |
+
|
274 |
+
jQuery.post(
|
275 |
+
myAjaxNonces.ajaxurl,
|
276 |
+
{
|
277 |
+
action: 'tvcajax-switch-feed-status',
|
278 |
+
feedId: feedId,
|
279 |
+
switchFeedStatusNonce: myAjaxNonces.switchFeedStatusNonce,
|
280 |
+
|
281 |
+
},
|
282 |
+
function( response ) {
|
283 |
+
|
284 |
+
tvc_switchStatusAction( feedId, response );
|
285 |
+
callback( tvc_validateResponse( response ) );
|
286 |
+
}
|
287 |
+
);
|
288 |
+
}
|
289 |
+
|
290 |
+
/**
|
291 |
+
* Duplicate/Clone existing feed
|
292 |
+
* @param feedId
|
293 |
+
* @param callback
|
294 |
+
*/
|
295 |
+
function tvc_duplicateExistingFeed( feedId, callback ) {
|
296 |
+
|
297 |
+
jQuery.post(
|
298 |
+
myAjaxNonces.ajaxurl,
|
299 |
+
{
|
300 |
+
action: 'tvcajax-duplicate-existing-feed',
|
301 |
+
feedId: feedId,
|
302 |
+
duplicateFeedNonce: myAjaxNonces.duplicateFeedNonce,
|
303 |
+
|
304 |
+
},
|
305 |
+
function( response ) {
|
306 |
+
|
307 |
+
if ( response.trim() ) {
|
308 |
+
tvc_resetFeedList();
|
309 |
+
}
|
310 |
+
|
311 |
+
callback( tvc_validateResponse( response ) );
|
312 |
+
}
|
313 |
+
);
|
314 |
+
}
|
315 |
+
|
316 |
+
/**
|
317 |
+
* Log message on server
|
318 |
+
* @param message
|
319 |
+
* @param fileName
|
320 |
+
* @param callback
|
321 |
+
*/
|
322 |
+
function tvc_logMessageOnServer( message, fileName, callback ) {
|
323 |
+
|
324 |
+
jQuery.post(
|
325 |
+
myAjaxNonces.ajaxurl,
|
326 |
+
{
|
327 |
+
action: 'tvcajax-log-message',
|
328 |
+
messageList: message,
|
329 |
+
fileName: fileName,
|
330 |
+
logMessageNonce: myAjaxNonces.logMessageNonce,
|
331 |
+
|
332 |
+
},
|
333 |
+
function( result ) {
|
334 |
+
|
335 |
+
callback( result.trim() );
|
336 |
+
}
|
337 |
+
);
|
338 |
+
}
|
339 |
+
|
340 |
+
function tvc_auto_feed_fix_mode( selection, callback ) {
|
341 |
+
|
342 |
+
jQuery.post(
|
343 |
+
myAjaxNonces.ajaxurl,
|
344 |
+
{
|
345 |
+
action: 'tvcajax-auto-feed-fix-mode-selection',
|
346 |
+
fix_selection: selection,
|
347 |
+
updateAutoFeedFixNonce: myAjaxNonces.setAutoFeedFixNonce,
|
348 |
+
|
349 |
+
},
|
350 |
+
function( response ) {
|
351 |
+
|
352 |
+
callback( response.trim() );
|
353 |
+
}
|
354 |
+
);
|
355 |
+
}
|
356 |
+
|
357 |
+
/**
|
358 |
+
* Ajax for background process of selected feeds
|
359 |
+
* @param selection
|
360 |
+
* @param callback
|
361 |
+
*/
|
362 |
+
function tvc_background_processing_mode( selection, callback ) {
|
363 |
+
|
364 |
+
jQuery.post(
|
365 |
+
myAjaxNonces.ajaxurl,
|
366 |
+
{
|
367 |
+
action: 'tvcajax-background-processing-mode-selection',
|
368 |
+
mode_selection: selection,
|
369 |
+
backgroundModeNonce: myAjaxNonces.setBackgroundModeNonce,
|
370 |
+
|
371 |
+
},
|
372 |
+
function( response ) {
|
373 |
+
|
374 |
+
callback( response.trim() );
|
375 |
+
}
|
376 |
+
);
|
377 |
+
}
|
378 |
+
|
379 |
+
function tvc_feed_logger_status( selection, callback ) {
|
380 |
+
|
381 |
+
jQuery.post(
|
382 |
+
myAjaxNonces.ajaxurl,
|
383 |
+
{
|
384 |
+
action: 'tvcajax-feed-logger-status-selection',
|
385 |
+
statusSelection: selection,
|
386 |
+
feedLoggerStatusNonce: myAjaxNonces.setFeedLoggerStatusNonce,
|
387 |
+
|
388 |
+
},
|
389 |
+
function( response ) {
|
390 |
+
|
391 |
+
callback( response.trim() );
|
392 |
+
}
|
393 |
+
);
|
394 |
+
}
|
395 |
+
|
396 |
+
/**
|
397 |
+
* Sets the Show Product Identifiers option.
|
398 |
+
*
|
399 |
+
* @since 2.10.0.
|
400 |
+
*
|
401 |
+
* @param selection
|
402 |
+
* @param callback
|
403 |
+
*/
|
404 |
+
function tvc_show_pi_status( selection, callback ) {
|
405 |
+
|
406 |
+
jQuery.post(
|
407 |
+
myAjaxNonces.ajaxurl,
|
408 |
+
{
|
409 |
+
action: 'tvcajax-show-product-identifiers-selection',
|
410 |
+
showPiSelection: selection,
|
411 |
+
showPINonce: myAjaxNonces.setShowPINonce,
|
412 |
+
|
413 |
+
},
|
414 |
+
function( response ) {
|
415 |
+
|
416 |
+
callback( response.trim() );
|
417 |
+
}
|
418 |
+
);
|
419 |
+
}
|
420 |
+
|
421 |
+
function tvc_change_third_party_attribute_keywords( keywords, callback ) {
|
422 |
+
|
423 |
+
jQuery.post(
|
424 |
+
myAjaxNonces.ajaxurl,
|
425 |
+
{
|
426 |
+
action: 'tvcajax-third-party-attribute-keywords',
|
427 |
+
keywords: keywords,
|
428 |
+
thirdPartyKeywordsNonce: myAjaxNonces.setThirdPartyKeywordsNonce,
|
429 |
+
|
430 |
+
},
|
431 |
+
function( response ) {
|
432 |
+
|
433 |
+
callback( response.trim() );
|
434 |
+
}
|
435 |
+
);
|
436 |
+
}
|
437 |
+
|
438 |
+
function tvc_change_notice_mailaddress( mailAddress, callback ) {
|
439 |
+
|
440 |
+
jQuery.post(
|
441 |
+
myAjaxNonces.ajaxurl,
|
442 |
+
{
|
443 |
+
action: 'tvcajax-set-notice-mailaddress',
|
444 |
+
mailaddress: mailAddress,
|
445 |
+
noticeMailaddressNonce: myAjaxNonces.setNoticeMailaddressNonce,
|
446 |
+
|
447 |
+
},
|
448 |
+
function( response ) {
|
449 |
+
|
450 |
+
callback( response.trim() );
|
451 |
+
}
|
452 |
+
);
|
453 |
+
}
|
454 |
+
|
455 |
+
function tvc_change_background_processing_time_limit( limit, callback ) {
|
456 |
+
|
457 |
+
jQuery.post(
|
458 |
+
myAjaxNonces.ajaxurl,
|
459 |
+
{
|
460 |
+
action: 'tvcajax-background-processing-time-limit',
|
461 |
+
limit: limit,
|
462 |
+
batchProcessingLimitNonce: myAjaxNonces.setBatchProcessingLimitNonce,
|
463 |
+
|
464 |
+
},
|
465 |
+
function( response ) {
|
466 |
+
|
467 |
+
callback( response.trim() );
|
468 |
+
}
|
469 |
+
);
|
470 |
+
}
|
471 |
+
|
472 |
+
function tvc_clear_feed_process_data( callback ) {
|
473 |
+
jQuery.post(
|
474 |
+
myAjaxNonces.ajaxurl,
|
475 |
+
{
|
476 |
+
action: 'tvcajax-clear-feed-process-data',
|
477 |
+
clearFeedNonce: myAjaxNonces.setClearFeedProcessNonce,
|
478 |
+
|
479 |
+
},
|
480 |
+
function( response ) {
|
481 |
+
|
482 |
+
callback( response );
|
483 |
+
}
|
484 |
+
);
|
485 |
+
}
|
486 |
+
|
487 |
+
function tvc_reinitiate_plugin( callback ) {
|
488 |
+
jQuery.post(
|
489 |
+
myAjaxNonces.ajaxurl,
|
490 |
+
{
|
491 |
+
action: 'tvcajax-reinitiate-plugin',
|
492 |
+
reInitiateNonce: myAjaxNonces.setReInitiateNonce,
|
493 |
+
|
494 |
+
},
|
495 |
+
function( response ) {
|
496 |
+
|
497 |
+
callback( response );
|
498 |
+
}
|
499 |
+
);
|
500 |
+
}
|
501 |
+
|
502 |
+
/**
|
503 |
+
* Takes the response of an ajax call and checks if it's ok. When not, it will display the error and return
|
504 |
+
* an empty list.
|
505 |
+
*
|
506 |
+
* @param {String} response
|
507 |
+
*
|
508 |
+
* @returns {String}
|
509 |
+
*/
|
510 |
+
function tvc_validateResponse( response ) {
|
511 |
+
|
512 |
+
response = response.trim(); // remove php ajax response white spaces
|
513 |
+
|
514 |
+
// when the response contains no error message
|
515 |
+
if ( response.indexOf( '<div id=\'error\'>' ) < 0 && response.indexOf( '<b>Fatal error</b>' ) < 0 && response.indexOf( '<b>Notice</b>' ) < 0 && response.indexOf( '<b>Warning</b>' ) < 0 && response.indexOf( '<b>Catchable fatal error</b>' ) < 0 && response.indexOf( '<div id="error">' ) < 0 ) {
|
516 |
+
|
517 |
+
if ( response.indexOf( '[]' ) < 0 ) {
|
518 |
+
|
519 |
+
if ( response !== '' ) {
|
520 |
+
|
521 |
+
return (
|
522 |
+
response
|
523 |
+
);
|
524 |
+
} else {
|
525 |
+
|
526 |
+
return (
|
527 |
+
'1'
|
528 |
+
);
|
529 |
+
}
|
530 |
+
} else { // if it has an error message
|
531 |
+
|
532 |
+
// return an empty list
|
533 |
+
return (
|
534 |
+
'0'
|
535 |
+
);
|
536 |
+
}
|
537 |
+
} else {
|
538 |
+
|
539 |
+
tvc_show_error_message( response.replace( '[]', '' ) );
|
540 |
+
tvc_hideFeedSpinner();
|
541 |
+
|
542 |
+
tvc_logMessageOnServer(
|
543 |
+
response,
|
544 |
+
'error',
|
545 |
+
function( result ) {
|
546 |
+
|
547 |
+
// return an empty list
|
548 |
+
return (
|
549 |
+
'0'
|
550 |
+
);
|
551 |
+
}
|
552 |
+
);
|
553 |
+
}
|
554 |
+
}
|
555 |
+
|
556 |
+
/**
|
557 |
+
* Deletes a specific feed file
|
558 |
+
*
|
559 |
+
* This function first removes the file from the server and than from the feed database.
|
560 |
+
* After that it will refresh the Feed List.
|
561 |
+
*
|
562 |
+
* @param {int} id
|
563 |
+
* @param {string} feedTitle
|
564 |
+
* @returns nothing
|
565 |
+
*/
|
566 |
+
function tvc_deleteFeed( id, feedTitle ) {
|
567 |
+
var feedSpinnerElement = jQuery( '#feed-spinner' );
|
568 |
+
var feedListMessageElement = jQuery( '#feed-list-message' );
|
569 |
+
|
570 |
+
// clear old messages
|
571 |
+
feedListMessageElement.empty();
|
572 |
+
|
573 |
+
// remove the file
|
574 |
+
tvc_removeFeedFile(
|
575 |
+
function() {
|
576 |
+
feedSpinnerElement.show();
|
577 |
+
|
578 |
+
// delete the file entry in the database
|
579 |
+
tvc_deleteFeedFromDb(
|
580 |
+
id,
|
581 |
+
function( response ) {
|
582 |
+
feedSpinnerElement.show();
|
583 |
+
|
584 |
+
response = response.trim();
|
585 |
+
|
586 |
+
if ( response === '1' ) {
|
587 |
+
// reset the feed list
|
588 |
+
tvc_resetFeedList();
|
589 |
+
feedSpinnerElement.hide();
|
590 |
+
} else {
|
591 |
+
// report the result to the user
|
592 |
+
feedListMessageElement.append( response );
|
593 |
+
feedSpinnerElement.hide();
|
594 |
+
}
|
595 |
+
},
|
596 |
+
id
|
597 |
+
);
|
598 |
+
},
|
599 |
+
feedTitle
|
600 |
+
);
|
601 |
+
}
|
602 |
+
|
603 |
+
function tvc_removeFeedFile( callback, feedTitle ) {
|
604 |
+
|
605 |
+
jQuery.post(
|
606 |
+
myAjaxNonces.ajaxurl,
|
607 |
+
{
|
608 |
+
action: 'tvcajax-delete-feed-file',
|
609 |
+
fileTitle: feedTitle,
|
610 |
+
deleteFeedNonce: myAjaxNonces.deleteFeedNonce,
|
611 |
+
|
612 |
+
},
|
613 |
+
function( response ) {
|
614 |
+
|
615 |
+
callback( tvc_validateResponse( response ) );
|
616 |
+
}
|
617 |
+
);
|
618 |
+
}
|
619 |
+
|
620 |
+
function tvc_deleteFeedFromDb( feedId, callback ) {
|
621 |
+
|
622 |
+
jQuery.post(
|
623 |
+
myAjaxNonces.ajaxurl,
|
624 |
+
{
|
625 |
+
action: 'tvcajax-delete-feed',
|
626 |
+
feedId: feedId,
|
627 |
+
deleteFeedNonce: myAjaxNonces.deleteFeedNonce,
|
628 |
+
|
629 |
+
},
|
630 |
+
function( response ) {
|
631 |
+
|
632 |
+
callback( tvc_validateResponse( response ) );
|
633 |
+
}
|
634 |
+
);
|
635 |
+
}
|
636 |
+
|
637 |
+
function tvc_checkNextFeedInQueue( callback ) {
|
638 |
+
jQuery.post(
|
639 |
+
myAjaxNonces.ajaxurl,
|
640 |
+
{
|
641 |
+
action: 'tvcajax-get-next-feed-in-queue',
|
642 |
+
nextFeedInQueueNonce: myAjaxNonces.nextFeedInQueueNonce,
|
643 |
+
|
644 |
+
},
|
645 |
+
function( response ) {
|
646 |
+
|
647 |
+
callback( tvc_validateResponse( response ) );
|
648 |
+
}
|
649 |
+
);
|
650 |
+
}
|
651 |
+
|
652 |
+
function tvc_initiateBackup( fileName, callback ) {
|
653 |
+
|
654 |
+
jQuery.post(
|
655 |
+
myAjaxNonces.ajaxurl,
|
656 |
+
{
|
657 |
+
action: 'tvcajax-backup-current-data',
|
658 |
+
fileName: fileName,
|
659 |
+
backupNonce: myAjaxNonces.backupNonce,
|
660 |
+
|
661 |
+
},
|
662 |
+
function( response ) {
|
663 |
+
|
664 |
+
callback( tvc_validateResponse( response ) );
|
665 |
+
}
|
666 |
+
);
|
667 |
+
}
|
668 |
+
|
669 |
+
function tvc_deleteBackup( fileName, callback ) {
|
670 |
+
|
671 |
+
jQuery.post(
|
672 |
+
myAjaxNonces.ajaxurl,
|
673 |
+
{
|
674 |
+
action: 'tvcajax-delete-backup-file',
|
675 |
+
fileName: fileName,
|
676 |
+
deleteBackupNonce: myAjaxNonces.deleteBackupNonce,
|
677 |
+
|
678 |
+
},
|
679 |
+
function( response ) {
|
680 |
+
|
681 |
+
callback( tvc_validateResponse( response ) );
|
682 |
+
}
|
683 |
+
);
|
684 |
+
}
|
685 |
+
|
686 |
+
function tvc_restoreBackup( fileName, callback ) {
|
687 |
+
|
688 |
+
jQuery.post(
|
689 |
+
myAjaxNonces.ajaxurl,
|
690 |
+
{
|
691 |
+
action: 'tvcajax-restore-backup-file',
|
692 |
+
fileName: fileName,
|
693 |
+
restoreBackupNonce: myAjaxNonces.restoreBackupNonce,
|
694 |
+
|
695 |
+
},
|
696 |
+
function( response ) {
|
697 |
+
|
698 |
+
callback( tvc_validateResponse( response ) );
|
699 |
+
}
|
700 |
+
);
|
701 |
+
}
|
702 |
+
|
703 |
+
function tvc_duplicateBackup( fileName, callback ) {
|
704 |
+
|
705 |
+
jQuery.post(
|
706 |
+
myAjaxNonces.ajaxurl,
|
707 |
+
{
|
708 |
+
action: 'tvcajax-duplicate-backup-file',
|
709 |
+
fileName: fileName,
|
710 |
+
duplicateBackupNonce: myAjaxNonces.duplicateBackupNonce,
|
711 |
+
|
712 |
+
},
|
713 |
+
function( response ) {
|
714 |
+
|
715 |
+
callback( tvc_validateResponse( response ) );
|
716 |
+
}
|
717 |
+
);
|
718 |
+
}
|
includes/data/js/tvc_ajaxdatahandling.min.js
ADDED
@@ -0,0 +1,364 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
var myAjaxNonces;
|
2 |
+
|
3 |
+
function tvc_getFeedList(a) {
|
4 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
5 |
+
action: "tvcajax-get-list-of-feeds",
|
6 |
+
postFeedsListNonce: myAjaxNonces.postFeedsListNonce
|
7 |
+
}, function (b) {
|
8 |
+
a(tvc_validateResponse(b))
|
9 |
+
})
|
10 |
+
}
|
11 |
+
|
12 |
+
function tvc_getBackupsList(a) {
|
13 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
14 |
+
action: "tvcajax-get-list-of-backups",
|
15 |
+
postBackupListNonce: myAjaxNonces.postBackupListNonce
|
16 |
+
}, function (b) {
|
17 |
+
a(tvc_validateResponse(b))
|
18 |
+
})
|
19 |
+
}
|
20 |
+
|
21 |
+
function tvc_getSettingsOptions(a) {
|
22 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
23 |
+
action: "tvcajax-get-settings-options",
|
24 |
+
postSetupOptionsNonce: myAjaxNonces.postSetupOptionsNonce
|
25 |
+
}, function (b) {
|
26 |
+
a(tvc_validateResponse(b))
|
27 |
+
})
|
28 |
+
}
|
29 |
+
|
30 |
+
function tvc_getOutputFields(a, b, c) {
|
31 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
32 |
+
action: "tvcajax-get-output-fields",
|
33 |
+
feedId: a,
|
34 |
+
channelId: b,
|
35 |
+
outputFieldsNonce: myAjaxNonces.outputFieldsNonce
|
36 |
+
}, function (d) {
|
37 |
+
c(tvc_validateResponse(d))
|
38 |
+
})
|
39 |
+
}
|
40 |
+
|
41 |
+
function tvc_getSourceFields(a, b) {
|
42 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
43 |
+
action: "tvcajax-get-input-fields",
|
44 |
+
sourceId: a,
|
45 |
+
inputFieldsNonce: myAjaxNonces.inputFieldsNonce
|
46 |
+
}, function (c) {
|
47 |
+
b(tvc_validateResponse(c))
|
48 |
+
})
|
49 |
+
}
|
50 |
+
|
51 |
+
function tvc_getMainFeedFilters(a, b) {
|
52 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
53 |
+
action: "tvcajax-get-main-feed-filters",
|
54 |
+
feedId: a,
|
55 |
+
inputFeedFiltersNonce: myAjaxNonces.inputFeedFiltersNonce
|
56 |
+
}, function (c) {
|
57 |
+
b(tvc_validateResponse(c))
|
58 |
+
})
|
59 |
+
}
|
60 |
+
|
61 |
+
function tvc_getNextCategories(c, b, a, e, d) {
|
62 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
63 |
+
action: "tvcajax-get-next-categories",
|
64 |
+
channelId: c,
|
65 |
+
requestedLevel: b,
|
66 |
+
parentCategory: a,
|
67 |
+
fileLanguage: e,
|
68 |
+
nextCategoryNonce: myAjaxNonces.nextCategoryNonce
|
69 |
+
}, function (f) {
|
70 |
+
f = f.trim();
|
71 |
+
if (f.substr(f.length - 1) === "0") {
|
72 |
+
f = f.substring(0, f.length - 1)
|
73 |
+
}
|
74 |
+
d(tvc_validateResponse(f))
|
75 |
+
})
|
76 |
+
}
|
77 |
+
|
78 |
+
function tvc_getCategoryListsFromString(b, a, d, c) {
|
79 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
80 |
+
action: "tvcajax-get-category-lists",
|
81 |
+
channelId: b,
|
82 |
+
mainCategories: a,
|
83 |
+
fileLanguage: d,
|
84 |
+
categoryListsNonce: myAjaxNonces.categoryListsNonce
|
85 |
+
}, function (e) {
|
86 |
+
c(tvc_validateResponse(e))
|
87 |
+
})
|
88 |
+
}
|
89 |
+
|
90 |
+
function tvc_updateFeedToDb(b, a, c, d) {
|
91 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
92 |
+
action: "tvcajax-update-feed-data",
|
93 |
+
feed: JSON.stringify(b),
|
94 |
+
feedFilter: c ? c[0]["meta_value"] : "",
|
95 |
+
metaData: JSON.stringify(a),
|
96 |
+
updateFeedDataNonce: myAjaxNonces.updateFeedDataNonce
|
97 |
+
}, function (e) {
|
98 |
+
d(tvc_validateResponse(e))
|
99 |
+
})
|
100 |
+
}
|
101 |
+
|
102 |
+
function tvc_updateFeedFile(a, b) {
|
103 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
104 |
+
action: "tvcajax-update-feed-file",
|
105 |
+
dataType: "text",
|
106 |
+
feedId: a,
|
107 |
+
updateFeedFileNonce: myAjaxNonces.updateFeedFileNonce
|
108 |
+
}, function (c) {
|
109 |
+
b(tvc_validateResponse(c))
|
110 |
+
})
|
111 |
+
}
|
112 |
+
|
113 |
+
function tvc_getCurrentFeedStatus(a, b) {
|
114 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
115 |
+
action: "tvcajax-get-feed-status",
|
116 |
+
sourceId: a,
|
117 |
+
feedStatusNonce: myAjaxNonces.feedStatusNonce
|
118 |
+
}, function (c) {
|
119 |
+
b(tvc_validateResponse(c))
|
120 |
+
})
|
121 |
+
}
|
122 |
+
|
123 |
+
function tvc_getFeedData(a, b) {
|
124 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
125 |
+
action: "tvcajax-get-feed-data",
|
126 |
+
sourceId: a,
|
127 |
+
feedDataNonce: myAjaxNonces.feedDataNonce
|
128 |
+
}, function (c) {
|
129 |
+
b(tvc_validateResponse(c))
|
130 |
+
})
|
131 |
+
}
|
132 |
+
|
133 |
+
function tvc_switchFeedStatus(a, b) {
|
134 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
135 |
+
action: "tvcajax-switch-feed-status",
|
136 |
+
feedId: a,
|
137 |
+
switchFeedStatusNonce: myAjaxNonces.switchFeedStatusNonce
|
138 |
+
}, function (c) {
|
139 |
+
tvc_switchStatusAction(a, c);
|
140 |
+
b(tvc_validateResponse(c))
|
141 |
+
})
|
142 |
+
}
|
143 |
+
|
144 |
+
function tvc_duplicateExistingFeed(a, b) {
|
145 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
146 |
+
action: "tvcajax-duplicate-existing-feed",
|
147 |
+
feedId: a,
|
148 |
+
duplicateFeedNonce: myAjaxNonces.duplicateFeedNonce
|
149 |
+
}, function (c) {
|
150 |
+
if (c.trim()) {
|
151 |
+
tvc_resetFeedList()
|
152 |
+
}
|
153 |
+
b(tvc_validateResponse(c))
|
154 |
+
})
|
155 |
+
}
|
156 |
+
|
157 |
+
function tvc_logMessageOnServer(a, c, b) {
|
158 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
159 |
+
action: "tvcajax-log-message",
|
160 |
+
messageList: a,
|
161 |
+
fileName: c,
|
162 |
+
logMessageNonce: myAjaxNonces.logMessageNonce
|
163 |
+
}, function (d) {
|
164 |
+
b(d.trim())
|
165 |
+
})
|
166 |
+
}
|
167 |
+
|
168 |
+
function tvc_auto_feed_fix_mode(a, b) {
|
169 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
170 |
+
action: "tvcajax-auto-feed-fix-mode-selection",
|
171 |
+
fix_selection: a,
|
172 |
+
updateAutoFeedFixNonce: myAjaxNonces.setAutoFeedFixNonce
|
173 |
+
}, function (c) {
|
174 |
+
b(c.trim())
|
175 |
+
})
|
176 |
+
}
|
177 |
+
|
178 |
+
function tvc_background_processing_mode(a, b) {
|
179 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
180 |
+
action: "tvcajax-background-processing-mode-selection",
|
181 |
+
mode_selection: a,
|
182 |
+
backgroundModeNonce: myAjaxNonces.setBackgroundModeNonce
|
183 |
+
}, function (c) {
|
184 |
+
b(c.trim())
|
185 |
+
})
|
186 |
+
}
|
187 |
+
|
188 |
+
function tvc_feed_logger_status(a, b) {
|
189 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
190 |
+
action: "tvcajax-feed-logger-status-selection",
|
191 |
+
statusSelection: a,
|
192 |
+
feedLoggerStatusNonce: myAjaxNonces.setFeedLoggerStatusNonce
|
193 |
+
}, function (c) {
|
194 |
+
b(c.trim())
|
195 |
+
})
|
196 |
+
}
|
197 |
+
|
198 |
+
function tvc_show_pi_status(a, b) {
|
199 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
200 |
+
action: "tvcajax-show-product-identifiers-selection",
|
201 |
+
showPiSelection: a,
|
202 |
+
showPINonce: myAjaxNonces.setShowPINonce
|
203 |
+
}, function (c) {
|
204 |
+
b(c.trim())
|
205 |
+
})
|
206 |
+
}
|
207 |
+
|
208 |
+
function tvc_change_third_party_attribute_keywords(a, b) {
|
209 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
210 |
+
action: "tvcajax-third-party-attribute-keywords",
|
211 |
+
keywords: a,
|
212 |
+
thirdPartyKeywordsNonce: myAjaxNonces.setThirdPartyKeywordsNonce
|
213 |
+
}, function (c) {
|
214 |
+
b(c.trim())
|
215 |
+
})
|
216 |
+
}
|
217 |
+
|
218 |
+
function tvc_change_notice_mailaddress(a, b) {
|
219 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
220 |
+
action: "tvcajax-set-notice-mailaddress",
|
221 |
+
mailaddress: a,
|
222 |
+
noticeMailaddressNonce: myAjaxNonces.setNoticeMailaddressNonce
|
223 |
+
}, function (c) {
|
224 |
+
b(c.trim())
|
225 |
+
})
|
226 |
+
}
|
227 |
+
|
228 |
+
function tvc_change_background_processing_time_limit(a, b) {
|
229 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
230 |
+
action: "tvcajax-background-processing-time-limit",
|
231 |
+
limit: a,
|
232 |
+
batchProcessingLimitNonce: myAjaxNonces.setBatchProcessingLimitNonce
|
233 |
+
}, function (c) {
|
234 |
+
b(c.trim())
|
235 |
+
})
|
236 |
+
}
|
237 |
+
|
238 |
+
function tvc_clear_feed_process_data(a) {
|
239 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
240 |
+
action: "tvcajax-clear-feed-process-data",
|
241 |
+
clearFeedNonce: myAjaxNonces.setClearFeedProcessNonce
|
242 |
+
}, function (b) {
|
243 |
+
a(b)
|
244 |
+
})
|
245 |
+
}
|
246 |
+
|
247 |
+
function tvc_reinitiate_plugin(a) {
|
248 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
249 |
+
action: "tvcajax-reinitiate-plugin",
|
250 |
+
reInitiateNonce: myAjaxNonces.setReInitiateNonce
|
251 |
+
}, function (b) {
|
252 |
+
a(b)
|
253 |
+
})
|
254 |
+
}
|
255 |
+
|
256 |
+
function tvc_validateResponse(a) {
|
257 |
+
a = a.trim();
|
258 |
+
if (a.indexOf("<div id='error'>") < 0 && a.indexOf("<b>Fatal error</b>") < 0 && a.indexOf("<b>Notice</b>") < 0 && a.indexOf("<b>Warning</b>") < 0 && a.indexOf("<b>Catchable fatal error</b>") < 0 && a.indexOf('<div id="error">') < 0) {
|
259 |
+
if (a.indexOf("[]") < 0) {
|
260 |
+
if (a !== "") {
|
261 |
+
return (a)
|
262 |
+
} else {
|
263 |
+
return ("1")
|
264 |
+
}
|
265 |
+
} else {
|
266 |
+
return ("0")
|
267 |
+
}
|
268 |
+
} else {
|
269 |
+
tvc_show_error_message(a.replace("[]", ""));
|
270 |
+
tvc_hideFeedSpinner();
|
271 |
+
tvc_logMessageOnServer(a, "error", function (b) {
|
272 |
+
return ("0")
|
273 |
+
})
|
274 |
+
}
|
275 |
+
}
|
276 |
+
|
277 |
+
function tvc_deleteFeed(d, b) {
|
278 |
+
var a = jQuery("#feed-spinner");
|
279 |
+
var c = jQuery("#feed-list-message");
|
280 |
+
c.empty();
|
281 |
+
tvc_removeFeedFile(function () {
|
282 |
+
a.show();
|
283 |
+
tvc_deleteFeedFromDb(d, function (e) {
|
284 |
+
a.show();
|
285 |
+
e = e.trim();
|
286 |
+
if (e === "1") {
|
287 |
+
tvc_resetFeedList();
|
288 |
+
a.hide()
|
289 |
+
} else {
|
290 |
+
c.append(e);
|
291 |
+
a.hide()
|
292 |
+
}
|
293 |
+
}, d)
|
294 |
+
}, b)
|
295 |
+
}
|
296 |
+
|
297 |
+
function tvc_removeFeedFile(b, a) {
|
298 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
299 |
+
action: "tvcajax-delete-feed-file",
|
300 |
+
fileTitle: a,
|
301 |
+
deleteFeedNonce: myAjaxNonces.deleteFeedNonce
|
302 |
+
}, function (c) {
|
303 |
+
b(tvc_validateResponse(c))
|
304 |
+
})
|
305 |
+
}
|
306 |
+
|
307 |
+
function tvc_deleteFeedFromDb(a, b) {
|
308 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
309 |
+
action: "tvcajax-delete-feed",
|
310 |
+
feedId: a,
|
311 |
+
deleteFeedNonce: myAjaxNonces.deleteFeedNonce
|
312 |
+
}, function (c) {
|
313 |
+
b(tvc_validateResponse(c))
|
314 |
+
})
|
315 |
+
}
|
316 |
+
|
317 |
+
function tvc_checkNextFeedInQueue(a) {
|
318 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
319 |
+
action: "tvcajax-get-next-feed-in-queue",
|
320 |
+
nextFeedInQueueNonce: myAjaxNonces.nextFeedInQueueNonce
|
321 |
+
}, function (b) {
|
322 |
+
a(tvc_validateResponse(b))
|
323 |
+
})
|
324 |
+
}
|
325 |
+
|
326 |
+
function tvc_initiateBackup(b, a) {
|
327 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
328 |
+
action: "tvcajax-backup-current-data",
|
329 |
+
fileName: b,
|
330 |
+
backupNonce: myAjaxNonces.backupNonce
|
331 |
+
}, function (c) {
|
332 |
+
a(tvc_validateResponse(c))
|
333 |
+
})
|
334 |
+
}
|
335 |
+
|
336 |
+
function tvc_deleteBackup(b, a) {
|
337 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
338 |
+
action: "tvcajax-delete-backup-file",
|
339 |
+
fileName: b,
|
340 |
+
deleteBackupNonce: myAjaxNonces.deleteBackupNonce
|
341 |
+
}, function (c) {
|
342 |
+
a(tvc_validateResponse(c))
|
343 |
+
})
|
344 |
+
}
|
345 |
+
|
346 |
+
function tvc_restoreBackup(b, a) {
|
347 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
348 |
+
action: "tvcajax-restore-backup-file",
|
349 |
+
fileName: b,
|
350 |
+
restoreBackupNonce: myAjaxNonces.restoreBackupNonce
|
351 |
+
}, function (c) {
|
352 |
+
a(tvc_validateResponse(c))
|
353 |
+
})
|
354 |
+
}
|
355 |
+
|
356 |
+
function tvc_duplicateBackup(b, a) {
|
357 |
+
jQuery.post(myAjaxNonces.ajaxurl, {
|
358 |
+
action: "tvcajax-duplicate-backup-file",
|
359 |
+
fileName: b,
|
360 |
+
duplicateBackupNonce: myAjaxNonces.duplicateBackupNonce
|
361 |
+
}, function (c) {
|
362 |
+
a(tvc_validateResponse(c))
|
363 |
+
})
|
364 |
+
};
|
includes/data/js/tvc_data.js
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"use strict";
|
2 |
+
/**
|
3 |
+
* Returns an array with all possible condition options
|
4 |
+
*
|
5 |
+
* @return {array} An array with possible condition options
|
6 |
+
*/
|
7 |
+
function tvc_queryOptionsEng() {
|
8 |
+
|
9 |
+
return [
|
10 |
+
'includes', 'does not include', 'is equal to', 'is not equal to', 'is empty', 'is not empty', 'starts with',
|
11 |
+
'does not start with', 'ends with', 'does not end with', 'is greater than', 'is greater or equal to', 'is smaller than',
|
12 |
+
'is smaller or equal to', 'is between'
|
13 |
+
];
|
14 |
+
}
|
15 |
+
|
16 |
+
function tvc_changeValuesOptions() {
|
17 |
+
|
18 |
+
return [ 'change nothing', 'overwrite', 'replace', 'remove', 'add prefix', 'add suffix', 'recalculate', 'convert to child-element' ];
|
19 |
+
}
|
20 |
+
|
21 |
+
function tvc_changeValuesRecalculateOptions() {
|
22 |
+
|
23 |
+
return [ 'add', 'subtract', 'multiply', 'divide' ];
|
24 |
+
}
|
25 |
+
|
26 |
+
function tvc_woocommerceSourceOptions() {
|
27 |
+
|
28 |
+
return [
|
29 |
+
{value: '_backorders', label: 'Allow Backorders', prop: 'meta'},
|
30 |
+
//{ value: '_button_text', label: 'Button Text', prop: 'meta' },
|
31 |
+
//{value:'', label:'Cross-Sells', prop:'meta'},
|
32 |
+
{value: '_height', label: 'Dimensions Height', prop: 'meta'},
|
33 |
+
{value: '_length', label: 'Dimensions Length', prop: 'meta'},
|
34 |
+
{value: '_width', label: 'Dimensions Width', prop: 'meta'},
|
35 |
+
{value: '_downloadable', label: 'Downloadable', prop: 'meta'},
|
36 |
+
//{value:'', label:'Enable Reviews', prop:'meta'},
|
37 |
+
{value: 'attachment_url', label: 'Featured Image', prop: 'main'}, // in the end this item will be handled procedural
|
38 |
+
//{value:'', label:'Grouping', prop:'meta'},
|
39 |
+
{value: 'item_group_id', label: 'Item Group Id', prop: 'main'},
|
40 |
+
{value: '_wp_attachement_metadata', label: 'Image Library', prop: 'main'},
|
41 |
+
{value: '_manage_stock', label: 'Manage Stock?', prop: 'meta'},
|
42 |
+
{value: '_max_variation_price', label: 'Max Variation Price', prop: 'meta'},
|
43 |
+
{value: '_max_variation_regular_price', label: 'Max Variation Regular Price', prop: 'meta'},
|
44 |
+
{value: '_max_variation_sale_price', label: 'Max Variation Sale Price', prop: 'meta'},
|
45 |
+
{value: 'menu_order', label: 'Menu Order', prop: 'meta'},
|
46 |
+
{value: '_min_variation_price', label: 'Min Variation Price', prop: 'meta'},
|
47 |
+
{value: '_min_variation_regular_price', label: 'Min Variation Regular Price', prop: 'meta'},
|
48 |
+
{value: '_min_variation_sale_price', label: 'Min Variation Sale Price', prop: 'meta'},
|
49 |
+
{value: 'post_author', label: 'Post Author', prop: 'post'},
|
50 |
+
{value: 'post_date', label: 'Post Date', prop: 'post'},
|
51 |
+
{value: 'post_date_gmt', label: 'Post Date GMT', prop: 'post'},
|
52 |
+
{value: 'ID', label: 'Post ID', prop: 'post'},
|
53 |
+
{value: 'post_modified', label: 'Post Modified', prop: 'post'},
|
54 |
+
{value: 'post_modified_gmt', label: 'Post Modified GMT', prop: 'post'},
|
55 |
+
{value: 'product_cat_string', label: 'Product Category String', prop: 'main'},
|
56 |
+
{value: 'post_content', label: 'Product Description', prop: 'post'},
|
57 |
+
{value: 'post_excerpt', label: 'Product Short Description', prop: 'post'},
|
58 |
+
{value: 'product_tags', label: 'Product Tags', prop: 'meta'},
|
59 |
+
{value: 'post_title', label: 'Product Title', prop: 'post'},
|
60 |
+
{value: 'tvc_product_brand', label: 'Product brand', prop: 'meta'},
|
61 |
+
{value: 'tvc_product_gtin', label: 'Product GTIN', prop: 'meta'},
|
62 |
+
{value: 'tvc_product_mpn', label: 'Product MPN', prop: 'meta'},
|
63 |
+
{value: 'product_variation_title_without_attributes', label: 'Product Title Without Variable Attributes', prop: 'meta'},
|
64 |
+
{value: 'product_type', label: 'Product Type', prop: 'meta'},
|
65 |
+
{value: 'permalink', label: 'Permalink', prop: 'post'},
|
66 |
+
//{value:'', label:'Purchase Note', prop:'meta'},
|
67 |
+
{value: '_regular_price', label: 'Regular Price', prop: 'meta'},
|
68 |
+
{value: '_sale_price', label: 'Sale Price', prop: 'meta'},
|
69 |
+
{value: '_sale_price_dates_from', label: 'Sale Price Dates From', prop: 'meta'},
|
70 |
+
{value: '_sale_price_dates_to', label: 'Sale Price Dates To', prop: 'meta'},
|
71 |
+
{value: 'product_cat', label: 'Selected Product Categories', prop: 'main'},
|
72 |
+
{value: 'fixed_shipping_price', label: 'Fixed Shipping Price', prop: 'main'},
|
73 |
+
{value: 'shipping_class', label: 'Shipping Class', prop: 'main'},
|
74 |
+
{value: '_sku', label: 'SKU', prop: 'meta'},
|
75 |
+
{value: '_sold_individually', label: 'Sold Individually', prop: 'meta'},
|
76 |
+
{value: '_stock', label: 'Stock Qty', prop: 'meta'},
|
77 |
+
{value: '_stock_status', label: 'Stock Status', prop: 'meta'},
|
78 |
+
{value: '_tax_status', label: 'Tax Status', prop: 'meta'},
|
79 |
+
{value: '_tax_class', label: 'Tax Class', prop: 'meta'},
|
80 |
+
//{value:'', label:'Up-Sells', prop:'meta'},
|
81 |
+
{value: '_virtual', label: 'Virtual', prop: 'meta'},
|
82 |
+
{value: '_weight', label: 'Weight', prop: 'meta'},
|
83 |
+
{value: 'wc_currency', label: 'WooCommerce Currency', prop: 'main'},
|
84 |
+
{value: 'last_update', label: 'Last Feed Update', prop: 'main'},
|
85 |
+
{value: 'empty', label: 'Remove from feed', prop: 'meta'},
|
86 |
+
];
|
87 |
+
}
|
88 |
+
|
89 |
+
function tvc_sourceOptionsConverter( optionValue ) {
|
90 |
+
|
91 |
+
var list = tvc_woocommerceSourceOptions();
|
92 |
+
|
93 |
+
for ( var key in list ) {
|
94 |
+
|
95 |
+
if ( list[ key ][ 'value' ] === optionValue ) {
|
96 |
+
return list[ key ][ 'label' ];
|
97 |
+
break;
|
98 |
+
}
|
99 |
+
}
|
100 |
+
}
|
101 |
+
|
102 |
+
function tvc_validateUrl( url ) {
|
103 |
+
var pattern = /^(?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?$/;
|
104 |
+
return ! ! pattern.test( url );
|
105 |
+
}
|
includes/data/js/tvc_data.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
function tvc_queryOptionsEng(){return["includes","does not include","is equal to","is not equal to","is empty","is not empty","starts with","does not start with","ends with","does not end with","is greater than","is greater or equal to","is smaller than","is smaller or equal to","is between"]}function tvc_changeValuesOptions(){return["change nothing","overwrite","replace","remove","add prefix","add suffix","recalculate","convert to child-element"]}function tvc_changeValuesRecalculateOptions(){return["add","subtract","multiply","divide"]}function tvc_woocommerceSourceOptions(){return[{value:"_backorders",label:"Allow Backorders",prop:"meta"},{value:"_height",label:"Dimensions Height",prop:"meta"},{value:"_length",label:"Dimensions Length",prop:"meta"},{value:"_width",label:"Dimensions Width",prop:"meta"},{value:"_downloadable",label:"Downloadable",prop:"meta"},{value:"attachment_url",label:"Featured Image",prop:"main"},{value:"item_group_id",label:"Item Group Id",prop:"main"},{value:"_wp_attachement_metadata",label:"Image Library",prop:"main"},{value:"_manage_stock",label:"Manage Stock?",prop:"meta"},{value:"_max_variation_price",label:"Max Variation Price",prop:"meta"},{value:"_max_variation_regular_price",label:"Max Variation Regular Price",prop:"meta"},{value:"_max_variation_sale_price",label:"Max Variation Sale Price",prop:"meta"},{value:"menu_order",label:"Menu Order",prop:"meta"},{value:"_min_variation_price",label:"Min Variation Price",prop:"meta"},{value:"_min_variation_regular_price",label:"Min Variation Regular Price",prop:"meta"},{value:"_min_variation_sale_price",label:"Min Variation Sale Price",prop:"meta"},{value:"post_author",label:"Post Author",prop:"post"},{value:"post_date",label:"Post Date",prop:"post"},{value:"post_date_gmt",label:"Post Date GMT",prop:"post"},{value:"ID",label:"Post ID",prop:"post"},{value:"post_modified",label:"Post Modified",prop:"post"},{value:"post_modified_gmt",label:"Post Modified GMT",prop:"post"},{value:"product_cat_string",label:"Product Category String",prop:"main"},{value:"post_content",label:"Product Description",prop:"post"},{value:"post_excerpt",label:"Product Short Description",prop:"post"},{value:"product_tags",label:"Product Tags",prop:"meta"},{value:"post_title",label:"Product Title",prop:"post"},{value:"tvc_product_brand",label:"Product brand",prop:"meta"},{value:"tvc_product_gtin",label:"Product GTIN",prop:"meta"},{value:"tvc_product_mpn",label:"Product MPN",prop:"meta"},{value:"product_variation_title_without_attributes",label:"Product Title Without Variable Attributes",prop:"meta"},{value:"product_type",label:"Product Type",prop:"meta"},{value:"permalink",label:"Permalink",prop:"post"},{value:"_regular_price",label:"Regular Price",prop:"meta"},{value:"_sale_price",label:"Sale Price",prop:"meta"},{value:"_sale_price_dates_from",label:"Sale Price Dates From",prop:"meta"},{value:"_sale_price_dates_to",label:"Sale Price Dates To",prop:"meta"},{value:"product_cat",label:"Selected Product Categories",prop:"main"},{value:"fixed_shipping_price",label:"Fixed Shipping Price",prop:"main"},{value:"shipping_class",label:"Shipping Class",prop:"main"},{value:"_sku",label:"SKU",prop:"meta"},{value:"_sold_individually",label:"Sold Individually",prop:"meta"},{value:"_stock",label:"Stock Qty",prop:"meta"},{value:"_stock_status",label:"Stock Status",prop:"meta"},{value:"_tax_status",label:"Tax Status",prop:"meta"},{value:"_tax_class",label:"Tax Class",prop:"meta"},{value:"_virtual",label:"Virtual",prop:"meta"},{value:"_weight",label:"Weight",prop:"meta"},{value:"wc_currency",label:"WooCommerce Currency",prop:"main"},{value:"last_update",label:"Last Feed Update",prop:"main"},{value:"empty",label:"Remove from feed",prop:"meta"}]}function tvc_sourceOptionsConverter(c){var b=tvc_woocommerceSourceOptions();for(var a in b){if(b[a]["value"]===c){return b[a]["label"];break}}}function tvc_validateUrl(a){var b=/^(?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?$/;return !!b.test(a)};
|
includes/data/js/tvc_feed-queue-string.js
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"use strict";
|
2 |
+
function tvcAddToQueueString( idToAdd ) {
|
3 |
+
var listElement = jQuery( '#tvc-feed-list-feeds-in-queue' );
|
4 |
+
|
5 |
+
if ( tvcQueueStringIsEmpty() ) {
|
6 |
+
listElement.text( idToAdd );
|
7 |
+
} else {
|
8 |
+
listElement.text( listElement.text() + ',' + idToAdd );
|
9 |
+
}
|
10 |
+
}
|
11 |
+
|
12 |
+
function tvcRemoveFromQueueString( idToRemove ) {
|
13 |
+
var listElement = jQuery( '#tvc-feed-list-feeds-in-queue' );
|
14 |
+
var currentString = listElement.text();
|
15 |
+
|
16 |
+
if ( currentString.indexOf( ',' ) > -1 ) {
|
17 |
+
currentString = currentString.endsWith( idToRemove ) ? currentString.replace( idToRemove, '' ) : currentString.replace( idToRemove + ',', '' );
|
18 |
+
listElement.text( currentString );
|
19 |
+
} else {
|
20 |
+
tvcClearQueueString();
|
21 |
+
}
|
22 |
+
}
|
23 |
+
|
24 |
+
function tvcQueueStringIsEmpty() {
|
25 |
+
return jQuery( '#tvc-feed-list-feeds-in-queue' ).text().length < 1;
|
26 |
+
}
|
27 |
+
|
28 |
+
function tvcClearQueueString() {
|
29 |
+
jQuery( '#tvc-feed-list-feeds-in-queue' ).text( '' );
|
30 |
+
}
|
includes/data/js/tvc_feed-queue-string.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
function tvcAddToQueueString(b){var a=jQuery("#tvc-feed-list-feeds-in-queue");if(tvcQueueStringIsEmpty()){a.text(b)}else{a.text(a.text()+","+b)}}function tvcRemoveFromQueueString(a){var c=jQuery("#tvc-feed-list-feeds-in-queue");var b=c.text();if(b.indexOf(",")>-1){b=b.endsWith(a)?b.replace(a,""):b.replace(a+",","");c.text(b)}else{tvcClearQueueString()}}function tvcQueueStringIsEmpty(){return jQuery("#tvc-feed-list-feeds-in-queue").text().length<1}function tvcClearQueueString(){jQuery("#tvc-feed-list-feeds-in-queue").text("")};
|
includes/data/js/tvc_metadatahandling.js
ADDED
@@ -0,0 +1,596 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
"use strict";
|
3 |
+
function tvc_storeSourceValue( level, currentMetaValue, type, valueToStore ) {
|
4 |
+
|
5 |
+
console.log( 'level:', level );
|
6 |
+
console.log( 'currentMetaValue:', currentMetaValue );
|
7 |
+
console.log( 'type:', type );
|
8 |
+
console.log( 'valueToStore:', valueToStore );
|
9 |
+
|
10 |
+
var o = currentMetaValue ? JSON.parse( currentMetaValue ) : {};
|
11 |
+
|
12 |
+
if ( o && 't' in o ) {
|
13 |
+
return currentMetaValue;
|
14 |
+
} // do not change the meta value if it contains the main category
|
15 |
+
|
16 |
+
if ( valueToStore && type !== 'clear' ) {
|
17 |
+
|
18 |
+
var t = {}, s = {};
|
19 |
+
|
20 |
+
s[ type ] = valueToStore;
|
21 |
+
|
22 |
+
t.s = s;
|
23 |
+
|
24 |
+
if ( o.hasOwnProperty( 'm' ) ) {
|
25 |
+
|
26 |
+
if ( ! o.m[ level ] ) {
|
27 |
+
|
28 |
+
o.m[ level ] = t;
|
29 |
+
} else {
|
30 |
+
|
31 |
+
o.m[ level ].s = s;
|
32 |
+
}
|
33 |
+
} else {
|
34 |
+
var m = [];
|
35 |
+
|
36 |
+
m.push( t );
|
37 |
+
o.m = m;
|
38 |
+
}
|
39 |
+
} else if ( type === 'clear' ) {
|
40 |
+
|
41 |
+
if ( o.hasOwnProperty( 'm' ) ) {
|
42 |
+
|
43 |
+
if ( o.m.length > 1 ) {
|
44 |
+
|
45 |
+
if ( ! o.m[ level ].c ) {
|
46 |
+
|
47 |
+
o.m.splice( level, 1 );
|
48 |
+
} else {
|
49 |
+
|
50 |
+
delete o.m[ level ].s;
|
51 |
+
}
|
52 |
+
} else {
|
53 |
+
|
54 |
+
delete o.m;
|
55 |
+
}
|
56 |
+
} else {
|
57 |
+
|
58 |
+
o = {};
|
59 |
+
}
|
60 |
+
}
|
61 |
+
|
62 |
+
var newValue = typeof (
|
63 |
+
o
|
64 |
+
) && ! jQuery.isEmptyObject( o ) ? JSON.stringify( o ) : '';
|
65 |
+
|
66 |
+
console.log( 'result:', newValue );
|
67 |
+
return newValue;
|
68 |
+
}
|
69 |
+
|
70 |
+
function tvc_storeConditionValue( sourceLevel, conditionLevel, currentMetaValue, newCondition ) {
|
71 |
+
|
72 |
+
console.log( 'sourceLevel:', sourceLevel );
|
73 |
+
console.log( 'conditionLevel:', conditionLevel );
|
74 |
+
console.log( 'currentMetaValue:', currentMetaValue );
|
75 |
+
console.log( 'newCondition:', newCondition );
|
76 |
+
|
77 |
+
var o = currentMetaValue ? JSON.parse( currentMetaValue ) : {};
|
78 |
+
var conditionPos = conditionLevel - 1;
|
79 |
+
var t = {};
|
80 |
+
var q = {};
|
81 |
+
|
82 |
+
if ( newCondition ) {
|
83 |
+
|
84 |
+
if ( ! o.hasOwnProperty( 'm' ) ) {
|
85 |
+
|
86 |
+
var m = [];
|
87 |
+
|
88 |
+
m.push( t );
|
89 |
+
o.m = m;
|
90 |
+
}
|
91 |
+
|
92 |
+
if ( o.m[ sourceLevel ] && o.m[ sourceLevel ].hasOwnProperty( 'c' ) ) {
|
93 |
+
|
94 |
+
q[ conditionLevel ] = newCondition;
|
95 |
+
|
96 |
+
if ( o.m[ sourceLevel ].c.hasOwnProperty( conditionPos ) ) {
|
97 |
+
|
98 |
+
o.m[ sourceLevel ].c[ conditionPos ] = q;
|
99 |
+
} else {
|
100 |
+
|
101 |
+
o.m[ sourceLevel ].c.push( q );
|
102 |
+
}
|
103 |
+
} else {
|
104 |
+
|
105 |
+
var c = [];
|
106 |
+
|
107 |
+
q[ conditionLevel ] = newCondition;
|
108 |
+
|
109 |
+
c.push( q );
|
110 |
+
|
111 |
+
t.c = c;
|
112 |
+
|
113 |
+
o.m[ sourceLevel ].c = c;
|
114 |
+
}
|
115 |
+
}
|
116 |
+
|
117 |
+
var newValue = typeof (
|
118 |
+
o
|
119 |
+
) && ! jQuery.isEmptyObject( o ) ? JSON.stringify( o ) : '';
|
120 |
+
|
121 |
+
console.log( 'result:', newValue );
|
122 |
+
return newValue;
|
123 |
+
}
|
124 |
+
|
125 |
+
function tvc_storeCombinedValue( sourceLevel, currentMetaValue, valueToStore ) {
|
126 |
+
|
127 |
+
console.log( 'sourceLevel:', sourceLevel );
|
128 |
+
console.log( 'currentMetaValue:', currentMetaValue );
|
129 |
+
console.log( 'valueToStore:', valueToStore );
|
130 |
+
|
131 |
+
var o = currentMetaValue ? JSON.parse( currentMetaValue ) : {};
|
132 |
+
|
133 |
+
if ( valueToStore ) {
|
134 |
+
|
135 |
+
var m = [], t = {}, s = {};
|
136 |
+
|
137 |
+
if ( ! o.hasOwnProperty( 'm' ) ) {
|
138 |
+
|
139 |
+
m.push( t );
|
140 |
+
o.m = m;
|
141 |
+
}
|
142 |
+
|
143 |
+
if ( ! o.m[ sourceLevel ].hasOwnProperty( 's' ) ) {
|
144 |
+
|
145 |
+
s[ 'source' ] = 'combined';
|
146 |
+
o.m[ sourceLevel ].s = s;
|
147 |
+
}
|
148 |
+
|
149 |
+
o.m[ sourceLevel ].s.f = valueToStore;
|
150 |
+
}
|
151 |
+
|
152 |
+
var newValue = typeof (
|
153 |
+
o
|
154 |
+
) && ! jQuery.isEmptyObject( o ) ? JSON.stringify( o ) : '';
|
155 |
+
|
156 |
+
console.log( 'result:', newValue );
|
157 |
+
|
158 |
+
return newValue;
|
159 |
+
}
|
160 |
+
|
161 |
+
function tvc_storeValueChange( sourceLevel, valueEditorLevel, valueToStore, action, currentMetaValue ) {
|
162 |
+
|
163 |
+
console.log( 'sourceLevel:', sourceLevel );
|
164 |
+
console.log( 'valueEditorLevel:', valueEditorLevel );
|
165 |
+
console.log( 'valueToStore:', valueToStore );
|
166 |
+
console.log( 'action:', action );
|
167 |
+
console.log( 'currentMetaValue:', currentMetaValue );
|
168 |
+
|
169 |
+
var o = currentMetaValue ? JSON.parse( currentMetaValue ) : {};
|
170 |
+
var t = {};
|
171 |
+
|
172 |
+
if ( valueToStore && action === 'add' ) {
|
173 |
+
|
174 |
+
t[ sourceLevel + 1 ] = valueToStore;
|
175 |
+
|
176 |
+
if ( o.hasOwnProperty( 'v' ) ) {
|
177 |
+
|
178 |
+
if ( o.v[ sourceLevel ] && o.v[ sourceLevel ].hasOwnProperty( 'q' ) ) {
|
179 |
+
|
180 |
+
o.v[ sourceLevel ][ valueEditorLevel + 1 ] = valueToStore;
|
181 |
+
} else {
|
182 |
+
|
183 |
+
o.v[ sourceLevel ] = t;
|
184 |
+
}
|
185 |
+
} else {
|
186 |
+
|
187 |
+
var v = [];
|
188 |
+
|
189 |
+
v.push( t );
|
190 |
+
o.v = v;
|
191 |
+
}
|
192 |
+
} else if ( action === 'clear' ) {
|
193 |
+
|
194 |
+
if ( 'v' in o ) {
|
195 |
+
|
196 |
+
if ( o.v.length > 1 ) {
|
197 |
+
|
198 |
+
if ( ! o.v[ sourceLevel ].q ) {
|
199 |
+
|
200 |
+
o.v.splice( sourceLevel, 1 );
|
201 |
+
} else {
|
202 |
+
|
203 |
+
delete o.v[ sourceLevel ].s;
|
204 |
+
}
|
205 |
+
} else {
|
206 |
+
|
207 |
+
delete o.v;
|
208 |
+
}
|
209 |
+
} else {
|
210 |
+
|
211 |
+
o = {};
|
212 |
+
}
|
213 |
+
}
|
214 |
+
|
215 |
+
var newValue = typeof (
|
216 |
+
o
|
217 |
+
) && ! jQuery.isEmptyObject( o ) ? JSON.stringify( o ) : '';
|
218 |
+
|
219 |
+
console.log( 'result:', newValue );
|
220 |
+
|
221 |
+
return newValue;
|
222 |
+
}
|
223 |
+
|
224 |
+
function tvc_removeCombinedValue( sourceLevel, combinedLevel, currentMetaValue ) {
|
225 |
+
|
226 |
+
console.log( 'sourceLevel:', sourceLevel );
|
227 |
+
console.log( 'combinedLevel:', combinedLevel );
|
228 |
+
console.log( 'currentMetaValue:', currentMetaValue );
|
229 |
+
|
230 |
+
var o = currentMetaValue ? JSON.parse( currentMetaValue ) : {};
|
231 |
+
|
232 |
+
if ( o.hasOwnProperty( 'm' ) && o.m[ sourceLevel ].hasOwnProperty( 's' ) && o.m[ sourceLevel ].s.hasOwnProperty( 'f' ) ) {
|
233 |
+
|
234 |
+
if ( o.m[ sourceLevel ].s.f ) {
|
235 |
+
|
236 |
+
var combinedValues = o.m[ sourceLevel ].s.f.split( '|' );
|
237 |
+
|
238 |
+
combinedValues.splice( combinedLevel - 1, 1 );
|
239 |
+
|
240 |
+
o.m[ sourceLevel ].s.f = tvc_makeCombinedValuesStringFromArray( combinedValues );
|
241 |
+
}
|
242 |
+
}
|
243 |
+
|
244 |
+
var newValue = typeof (
|
245 |
+
o
|
246 |
+
) && ! jQuery.isEmptyObject( o ) ? JSON.stringify( o ) : '';
|
247 |
+
|
248 |
+
console.log( 'result:', newValue );
|
249 |
+
|
250 |
+
return newValue;
|
251 |
+
}
|
252 |
+
|
253 |
+
function tvc_removeConditionValue( sourceLevel, conditionLevel, currentMetaValue ) {
|
254 |
+
|
255 |
+
console.log( 'sourceLevel:', sourceLevel );
|
256 |
+
console.log( 'conditionLevel:', conditionLevel );
|
257 |
+
console.log( 'currentMetaValue:', currentMetaValue );
|
258 |
+
|
259 |
+
var o = currentMetaValue ? JSON.parse( currentMetaValue ) : {};
|
260 |
+
var coi = null;
|
261 |
+
|
262 |
+
if ( o && o.hasOwnProperty( 'm' ) && o.m[ sourceLevel ] && o.m[ sourceLevel ].hasOwnProperty( 'c' ) ) {
|
263 |
+
|
264 |
+
if ( o.m[ sourceLevel ].c[ conditionLevel ] ) {
|
265 |
+
|
266 |
+
if ( o.m[ sourceLevel ].c.length > 1 ) {
|
267 |
+
|
268 |
+
// remove the correct condition
|
269 |
+
o.m[ sourceLevel ].c.splice( conditionLevel, 1 );
|
270 |
+
|
271 |
+
// and resort the remaining conditions
|
272 |
+
o.m[ sourceLevel ].c = tvc_resortObject( o.m[ sourceLevel ].c );
|
273 |
+
} else {
|
274 |
+
|
275 |
+
// check what is left in the mapping part
|
276 |
+
coi = tvc_countObjectItems( o.m );
|
277 |
+
|
278 |
+
if ( coi > 2 ) {
|
279 |
+
|
280 |
+
o.m.splice( [ sourceLevel ], 1 );
|
281 |
+
} else {
|
282 |
+
|
283 |
+
if ( coi < 1 ) {
|
284 |
+
|
285 |
+
if ( o.hasOwnProperty( 'v' ) ) {
|
286 |
+
|
287 |
+
// when the object also has a v element only remove the m element
|
288 |
+
delete o.m[ sourceLevel ];
|
289 |
+
} else {
|
290 |
+
|
291 |
+
// but when the object only has an m element then empty the object
|
292 |
+
o = {};
|
293 |
+
}
|
294 |
+
} else {
|
295 |
+
|
296 |
+
if ( o.m[ sourceLevel ].hasOwnProperty( 's' ) ) {
|
297 |
+
|
298 |
+
// remove the condition
|
299 |
+
delete o.m[ sourceLevel ].c;
|
300 |
+
|
301 |
+
// and remove the source that was selected as the condition would be met
|
302 |
+
o.m.splice( [ sourceLevel + 1 ], 1 );
|
303 |
+
} else {
|
304 |
+
|
305 |
+
if ( o.hasOwnProperty( 'v' ) ) {
|
306 |
+
|
307 |
+
// when the object also has a v element only remove the m element
|
308 |
+
delete o.m[ sourceLevel ];
|
309 |
+
} else {
|
310 |
+
|
311 |
+
// but when the object only has an m element then empty the object
|
312 |
+
o = {};
|
313 |
+
}
|
314 |
+
}
|
315 |
+
}
|
316 |
+
}
|
317 |
+
}
|
318 |
+
}
|
319 |
+
} else if ( o && o.hasOwnProperty( 'm' ) && o.m[ sourceLevel ] && o.m[ sourceLevel ].hasOwnProperty( 's' ) ) {
|
320 |
+
|
321 |
+
coi = tvc_countObjectItems( o.m );
|
322 |
+
|
323 |
+
if ( coi > 1 ) {
|
324 |
+
|
325 |
+
o.m.splice( [ sourceLevel ], 1 );
|
326 |
+
} else {
|
327 |
+
|
328 |
+
if ( o.hasOwnProperty( 'v' ) ) {
|
329 |
+
|
330 |
+
// when the object also has a v element only remove the m element
|
331 |
+
delete o.m[ sourceLevel ];
|
332 |
+
} else {
|
333 |
+
|
334 |
+
// but when the object only has an m element then empty the object
|
335 |
+
o = {};
|
336 |
+
}
|
337 |
+
}
|
338 |
+
}
|
339 |
+
|
340 |
+
var newValue = typeof (
|
341 |
+
o
|
342 |
+
) && ! jQuery.isEmptyObject( o ) ? JSON.stringify( o ) : '';
|
343 |
+
|
344 |
+
console.log( 'result:', newValue );
|
345 |
+
|
346 |
+
return newValue;
|
347 |
+
}
|
348 |
+
|
349 |
+
function tvc_removeQueryValue( sourceLevel, conditionLevel, currentMetaValue ) {
|
350 |
+
|
351 |
+
console.log( 'sourceLevel:', sourceLevel );
|
352 |
+
console.log( 'conditionLevel:', conditionLevel );
|
353 |
+
console.log( 'currentMetaValue:', currentMetaValue );
|
354 |
+
|
355 |
+
var o = currentMetaValue ? JSON.parse( currentMetaValue ) : {};
|
356 |
+
|
357 |
+
if ( o && o.hasOwnProperty( 'v' ) && o.v[ sourceLevel ] && o.v[ sourceLevel ].hasOwnProperty( 'q' ) ) {
|
358 |
+
|
359 |
+
if ( o.v[ sourceLevel ].q[ conditionLevel - 1 ] ) {
|
360 |
+
|
361 |
+
if ( o.v[ sourceLevel ].q.length > 1 ) {
|
362 |
+
|
363 |
+
// remove the correct condition
|
364 |
+
o.v[ sourceLevel ].q.splice( ( conditionLevel - 1 ), 1 );
|
365 |
+
|
366 |
+
// and resort the remaining conditions
|
367 |
+
o.v[ sourceLevel ].q = tvc_resortObject( o.v[ sourceLevel ].q );
|
368 |
+
} else {
|
369 |
+
|
370 |
+
// check what is left in the mapping part
|
371 |
+
var coi = tvc_countObjectItems( o.v );
|
372 |
+
|
373 |
+
if ( coi > 2 ) {
|
374 |
+
|
375 |
+
o.v.splice( [ sourceLevel ], 1 );
|
376 |
+
} else {
|
377 |
+
|
378 |
+
if ( coi < 1 ) {
|
379 |
+
|
380 |
+
if ( o.hasOwnProperty( 'm' ) ) {
|
381 |
+
|
382 |
+
// when the object also has an m element only remove the v element
|
383 |
+
delete o.v[ sourceLevel ];
|
384 |
+
} else {
|
385 |
+
|
386 |
+
// but when the object only has a v element then empty the object
|
387 |
+
o = {};
|
388 |
+
}
|
389 |
+
} else {
|
390 |
+
|
391 |
+
if ( o.v[ sourceLevel ].hasOwnProperty( '1' ) ) {
|
392 |
+
|
393 |
+
// remove the condition
|
394 |
+
delete o.v[ sourceLevel ].q;
|
395 |
+
} else {
|
396 |
+
|
397 |
+
if ( o.hasOwnProperty( 'm' ) ) {
|
398 |
+
|
399 |
+
// when the object also has an m element only remove the v element
|
400 |
+
delete o.v[ sourceLevel ];
|
401 |
+
} else {
|
402 |
+
|
403 |
+
// but when the object only has an m element then empty the object
|
404 |
+
o = {};
|
405 |
+
}
|
406 |
+
}
|
407 |
+
}
|
408 |
+
}
|
409 |
+
}
|
410 |
+
}
|
411 |
+
}
|
412 |
+
|
413 |
+
var newValue = typeof (
|
414 |
+
o
|
415 |
+
) && ! jQuery.isEmptyObject( o ) ? JSON.stringify( o ) : '';
|
416 |
+
|
417 |
+
console.log( 'result:', newValue );
|
418 |
+
|
419 |
+
return newValue;
|
420 |
+
}
|
421 |
+
|
422 |
+
function tvc_removeEditValuesValue( sourceLevel, valueEditorLevel, currentMetaValue ) {
|
423 |
+
|
424 |
+
console.log( 'sourceLevel:', sourceLevel );
|
425 |
+
console.log( 'valueEditorLevel:', valueEditorLevel );
|
426 |
+
console.log( 'currentMetaValue:', currentMetaValue );
|
427 |
+
|
428 |
+
var o = currentMetaValue ? JSON.parse( currentMetaValue ) : {};
|
429 |
+
|
430 |
+
if ( 'v' in o ) {
|
431 |
+
|
432 |
+
if ( o.v.length > 1 ) {
|
433 |
+
|
434 |
+
o.v.splice( sourceLevel, 1 );
|
435 |
+
} else {
|
436 |
+
|
437 |
+
delete o.v;
|
438 |
+
}
|
439 |
+
} else {
|
440 |
+
|
441 |
+
o = {};
|
442 |
+
}
|
443 |
+
|
444 |
+
var newValue = typeof (
|
445 |
+
o
|
446 |
+
) && ! jQuery.isEmptyObject( o ) ? JSON.stringify( o ) : '';
|
447 |
+
|
448 |
+
console.log( 'result:', newValue );
|
449 |
+
|
450 |
+
return newValue;
|
451 |
+
|
452 |
+
}
|
453 |
+
|
454 |
+
function tvc_storeQueryValue( sourceLevel, queryLevel, currentMetaValue, newQuery ) {
|
455 |
+
|
456 |
+
console.log( 'sourceLevel:', sourceLevel );
|
457 |
+
console.log( 'queryLevel:', queryLevel );
|
458 |
+
console.log( 'currentMetaValue:', currentMetaValue );
|
459 |
+
console.log( 'newQuery:', newQuery );
|
460 |
+
|
461 |
+
var o = currentMetaValue ? JSON.parse( currentMetaValue ) : {};
|
462 |
+
var conditionPos = queryLevel - 1;
|
463 |
+
var t = {};
|
464 |
+
var vq = {};
|
465 |
+
|
466 |
+
if ( newQuery ) {
|
467 |
+
|
468 |
+
if ( ! o.hasOwnProperty( 'v' ) ) {
|
469 |
+
|
470 |
+
var v = [];
|
471 |
+
|
472 |
+
v.push( t );
|
473 |
+
o.v = v;
|
474 |
+
}
|
475 |
+
|
476 |
+
if ( o.v[ sourceLevel ] && o.v[ sourceLevel ].hasOwnProperty( 'q' ) ) {
|
477 |
+
|
478 |
+
vq[ queryLevel ] = newQuery;
|
479 |
+
|
480 |
+
if ( o.v[ sourceLevel ].q.hasOwnProperty( conditionPos ) ) {
|
481 |
+
|
482 |
+
o.v[ sourceLevel ].q[ conditionPos ] = vq;
|
483 |
+
} else {
|
484 |
+
|
485 |
+
o.v[ sourceLevel ].q.push( vq );
|
486 |
+
}
|
487 |
+
} else {
|
488 |
+
|
489 |
+
var q = [];
|
490 |
+
|
491 |
+
vq[ queryLevel ] = newQuery;
|
492 |
+
|
493 |
+
q.push( vq );
|
494 |
+
|
495 |
+
t.q = q;
|
496 |
+
|
497 |
+
o.v[ sourceLevel ].q = q;
|
498 |
+
}
|
499 |
+
}
|
500 |
+
|
501 |
+
var newValue = typeof (
|
502 |
+
o
|
503 |
+
) && ! jQuery.isEmptyObject( o ) ? JSON.stringify( o ) : '';
|
504 |
+
|
505 |
+
console.log( 'result:', newValue );
|
506 |
+
return newValue;
|
507 |
+
}
|
508 |
+
|
509 |
+
function tvc_makeCombinedValuesStringFromArray( combinedValuesArray ) {
|
510 |
+
|
511 |
+
var combinedValuesString = '';
|
512 |
+
|
513 |
+
for ( var i = 0; i < combinedValuesArray.length; i ++ ) {
|
514 |
+
|
515 |
+
combinedValuesString += combinedValuesArray[ i ];
|
516 |
+
combinedValuesString += i < (
|
517 |
+
combinedValuesArray.length - 1
|
518 |
+
) ? '|' : '';
|
519 |
+
}
|
520 |
+
|
521 |
+
return combinedValuesString;
|
522 |
+
}
|
523 |
+
|
524 |
+
function changeFeedFilterValue( workValue, newValues, changedFilterLevel ) {
|
525 |
+
|
526 |
+
console.log( 'workValue:', workValue );
|
527 |
+
console.log( 'newValues:', newValues );
|
528 |
+
console.log( 'changedFilterLevel:', changedFilterLevel );
|
529 |
+
|
530 |
+
var filterObject = [];
|
531 |
+
|
532 |
+
if ( workValue ) {
|
533 |
+
filterObject = JSON.parse( workValue[ 0 ][ 'meta_value' ] );
|
534 |
+
} else {
|
535 |
+
filterObject = [];
|
536 |
+
|
537 |
+
workValue = []; // build a new empty workValue
|
538 |
+
var m = {'meta_value': ''};
|
539 |
+
workValue.push( m );
|
540 |
+
}
|
541 |
+
|
542 |
+
var nrFilters = filterObject.length;
|
543 |
+
|
544 |
+
var newValueString = newValues[ 0 ] + '#' + newValues[ 1 ] + '#' + newValues[ 2 ];
|
545 |
+
newValueString += newValues[ 2 ] !== '4' && newValues[ 2 ] !== '5' ? '#' + newValues[ 3 ] : '';
|
546 |
+
|
547 |
+
if ( changedFilterLevel <= nrFilters ) {
|
548 |
+
filterObject[ changedFilterLevel - 1 ][ changedFilterLevel ] = newValueString;
|
549 |
+
} else {
|
550 |
+
|
551 |
+
var n = {};
|
552 |
+
|
553 |
+
n[ changedFilterLevel ] = newValueString;
|
554 |
+
//filterObject.push( n );
|
555 |
+
filterObject[ changedFilterLevel - 1 ] = n;
|
556 |
+
}
|
557 |
+
|
558 |
+
workValue[ 0 ][ 'meta_value' ] = JSON.stringify( filterObject );
|
559 |
+
|
560 |
+
console.log( 'result:', JSON.stringify( workValue ) );
|
561 |
+
|
562 |
+
return workValue;
|
563 |
+
}
|
564 |
+
|
565 |
+
function removeFeedFilterLevel( workValue, levelToRemove ) {
|
566 |
+
|
567 |
+
console.log( 'workValue:', workValue );
|
568 |
+
console.log( 'levelToRemove:', levelToRemove );
|
569 |
+
|
570 |
+
var filterObject = workValue ? JSON.parse( workValue[ 0 ][ 'meta_value' ] ) : {};
|
571 |
+
var returnFilterObject = [];
|
572 |
+
var i = 0;
|
573 |
+
|
574 |
+
for ( var key in filterObject ) {
|
575 |
+
|
576 |
+
if ( parseInt( key ) !== levelToRemove - 1 ) {
|
577 |
+
|
578 |
+
var v = {};
|
579 |
+
v[ i + 1 ] = filterObject[ key ][ parseInt( key ) + 1 ];
|
580 |
+
|
581 |
+
returnFilterObject[ i ] = v;
|
582 |
+
|
583 |
+
i ++;
|
584 |
+
}
|
585 |
+
}
|
586 |
+
|
587 |
+
if ( returnFilterObject.length > 0 ) {
|
588 |
+
workValue[ 0 ][ 'meta_value' ] = JSON.stringify( returnFilterObject );
|
589 |
+
console.log( 'result:', JSON.stringify( workValue ) );
|
590 |
+
} else {
|
591 |
+
workValue = '';
|
592 |
+
console.log( 'result:', workValue );
|
593 |
+
}
|
594 |
+
|
595 |
+
return workValue;
|
596 |
+
}
|
includes/data/js/tvc_metadatahandling.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
function tvc_storeSourceValue(a,b,g,c){console.log("level:",a);console.log("currentMetaValue:",b);console.log("type:",g);console.log("valueToStore:",c);var e=b?JSON.parse(b):{};if(e&&"t" in e){return b}if(c&&g!=="clear"){var h={},i={};i[g]=c;h.s=i;if(e.hasOwnProperty("m")){if(!e.m[a]){e.m[a]=h}else{e.m[a].s=i}}else{var f=[];f.push(h);e.m=f}}else{if(g==="clear"){if(e.hasOwnProperty("m")){if(e.m.length>1){if(!e.m[a].c){e.m.splice(a,1)}else{delete e.m[a].s}}else{delete e.m}}else{e={}}}}var d=typeof(e)&&!jQuery.isEmptyObject(e)?JSON.stringify(e):"";console.log("result:",d);return d}function tvc_storeConditionValue(a,l,d,g){console.log("sourceLevel:",a);console.log("conditionLevel:",l);console.log("currentMetaValue:",d);console.log("newCondition:",g);var f=d?JSON.parse(d):{};var j=l-1;var k={};var b={};if(g){if(!f.hasOwnProperty("m")){var h=[];h.push(k);f.m=h}if(f.m[a]&&f.m[a].hasOwnProperty("c")){b[l]=g;if(f.m[a].c.hasOwnProperty(j)){f.m[a].c[j]=b}else{f.m[a].c.push(b)}}else{var i=[];b[l]=g;i.push(b);k.c=i;f.m[a].c=i}}var e=typeof(f)&&!jQuery.isEmptyObject(f)?JSON.stringify(f):"";console.log("result:",e);return e}function tvc_storeCombinedValue(f,c,b){console.log("sourceLevel:",f);console.log("currentMetaValue:",c);console.log("valueToStore:",b);var h=c?JSON.parse(c):{};if(b){var a=[],d={},e={};if(!h.hasOwnProperty("m")){a.push(d);h.m=a}if(!h.m[f].hasOwnProperty("s")){e.source="combined";h.m[f].s=e}h.m[f].s.f=b}var g=typeof(h)&&!jQuery.isEmptyObject(h)?JSON.stringify(h):"";console.log("result:",g);return g}function tvc_storeValueChange(a,g,b,f,c){console.log("sourceLevel:",a);console.log("valueEditorLevel:",g);console.log("valueToStore:",b);console.log("action:",f);console.log("currentMetaValue:",c);var e=c?JSON.parse(c):{};var i={};if(b&&f==="add"){i[a+1]=b;if(e.hasOwnProperty("v")){if(e.v[a]&&e.v[a].hasOwnProperty("q")){e.v[a][g+1]=b}else{e.v[a]=i}}else{var h=[];h.push(i);e.v=h}}else{if(f==="clear"){if("v" in e){if(e.v.length>1){if(!e.v[a].q){e.v.splice(a,1)}else{delete e.v[a].s}}else{delete e.v}}else{e={}}}}var d=typeof(e)&&!jQuery.isEmptyObject(e)?JSON.stringify(e):"";console.log("result:",d);return d}function tvc_removeCombinedValue(d,c,a){console.log("sourceLevel:",d);console.log("combinedLevel:",c);console.log("currentMetaValue:",a);var f=a?JSON.parse(a):{};if(f.hasOwnProperty("m")&&f.m[d].hasOwnProperty("s")&&f.m[d].s.hasOwnProperty("f")){if(f.m[d].s.f){var b=f.m[d].s.f.split("|");b.splice(c-1,1);f.m[d].s.f=tvc_makeCombinedValuesStringFromArray(b)}}var e=typeof(f)&&!jQuery.isEmptyObject(f)?JSON.stringify(f):"";console.log("result:",e);return e}function tvc_removeConditionValue(d,b,a){console.log("sourceLevel:",d);console.log("conditionLevel:",b);console.log("currentMetaValue:",a);var f=a?JSON.parse(a):{};var c=null;if(f&&f.hasOwnProperty("m")&&f.m[d]&&f.m[d].hasOwnProperty("c")){if(f.m[d].c[b]){if(f.m[d].c.length>1){f.m[d].c.splice(b,1);f.m[d].c=tvc_resortObject(f.m[d].c)}else{c=tvc_countObjectItems(f.m);if(c>2){f.m.splice([d],1)}else{if(c<1){if(f.hasOwnProperty("v")){delete f.m[d]}else{f={}}}else{if(f.m[d].hasOwnProperty("s")){delete f.m[d].c;f.m.splice([d+1],1)}else{if(f.hasOwnProperty("v")){delete f.m[d]}else{f={}}}}}}}}else{if(f&&f.hasOwnProperty("m")&&f.m[d]&&f.m[d].hasOwnProperty("s")){c=tvc_countObjectItems(f.m);if(c>1){f.m.splice([d],1)}else{if(f.hasOwnProperty("v")){delete f.m[d]}else{f={}}}}}var e=typeof(f)&&!jQuery.isEmptyObject(f)?JSON.stringify(f):"";console.log("result:",e);return e}function tvc_removeQueryValue(d,b,a){console.log("sourceLevel:",d);console.log("conditionLevel:",b);console.log("currentMetaValue:",a);var f=a?JSON.parse(a):{};if(f&&f.hasOwnProperty("v")&&f.v[d]&&f.v[d].hasOwnProperty("q")){if(f.v[d].q[b-1]){if(f.v[d].q.length>1){f.v[d].q.splice((b-1),1);f.v[d].q=tvc_resortObject(f.v[d].q)}else{var c=tvc_countObjectItems(f.v);if(c>2){f.v.splice([d],1)}else{if(c<1){if(f.hasOwnProperty("m")){delete f.v[d]}else{f={}}}else{if(f.v[d].hasOwnProperty("1")){delete f.v[d].q}else{if(f.hasOwnProperty("m")){delete f.v[d]}else{f={}}}}}}}}var e=typeof(f)&&!jQuery.isEmptyObject(f)?JSON.stringify(f):"";console.log("result:",e);return e}function tvc_removeEditValuesValue(b,e,a){console.log("sourceLevel:",b);console.log("valueEditorLevel:",e);console.log("currentMetaValue:",a);var d=a?JSON.parse(a):{};if("v" in d){if(d.v.length>1){d.v.splice(b,1)}else{delete d.v}}else{d={}}var c=typeof(d)&&!jQuery.isEmptyObject(d)?JSON.stringify(d):"";console.log("result:",c);return c}function tvc_storeQueryValue(c,g,d,k){console.log("sourceLevel:",c);console.log("queryLevel:",g);console.log("currentMetaValue:",d);console.log("newQuery:",k);var f=d?JSON.parse(d):{};var h=g-1;var j={};var a={};if(k){if(!f.hasOwnProperty("v")){var i=[];i.push(j);f.v=i}if(f.v[c]&&f.v[c].hasOwnProperty("q")){a[g]=k;if(f.v[c].q.hasOwnProperty(h)){f.v[c].q[h]=a}else{f.v[c].q.push(a)}}else{var b=[];a[g]=k;b.push(a);j.q=b;f.v[c].q=b}}var e=typeof(f)&&!jQuery.isEmptyObject(f)?JSON.stringify(f):"";console.log("result:",e);return e}function tvc_makeCombinedValuesStringFromArray(b){var a="";for(var c=0;c<b.length;c++){a+=b[c];a+=c<(b.length-1)?"|":""}return a}function changeFeedFilterValue(g,c,f){console.log("workValue:",g);console.log("newValues:",c);console.log("changedFilterLevel:",f);var e=[];if(g){e=JSON.parse(g[0]["meta_value"])}else{e=[];g=[];var a={meta_value:""};g.push(a)}var d=e.length;var b=c[0]+"#"+c[1]+"#"+c[2];b+=c[2]!=="4"&&c[2]!=="5"?"#"+c[3]:"";if(f<=d){e[f-1][f]=b}else{var h={};h[f]=b;e[f-1]=h}g[0]["meta_value"]=JSON.stringify(e);console.log("result:",JSON.stringify(g));return g}function removeFeedFilterLevel(f,g){console.log("workValue:",f);console.log("levelToRemove:",g);var e=f?JSON.parse(f[0]["meta_value"]):{};var d=[];var c=0;for(var b in e){if(parseInt(b)!==g-1){var a={};a[c+1]=e[b][parseInt(b)+1];d[c]=a;c++}}if(d.length>0){f[0]["meta_value"]=JSON.stringify(d);console.log("result:",JSON.stringify(f))}else{f="";console.log("result:",f)}return f};
|
includes/data/tvc-admin-functions.php
ADDED
@@ -0,0 +1,372 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* @package TVC Product Feed Manager/Data/Functions
|
5 |
+
* @version 2.7.0
|
6 |
+
*/
|
7 |
+
|
8 |
+
if ( ! defined( 'ABSPATH' ) ) {
|
9 |
+
exit;
|
10 |
+
}
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Converts a string containing a date-time stamp as stored in the meta data to a date time string
|
14 |
+
* that can be used in a feed file
|
15 |
+
*
|
16 |
+
* @param string $date_stamp The timestamp that needs to be converted to a string that can be stored in a feed file
|
17 |
+
*
|
18 |
+
* @return string A string containing the time or an empty string if the $date_stamp is empty
|
19 |
+
* @since 1.1.0
|
20 |
+
*
|
21 |
+
*/
|
22 |
+
function tvc_convert_price_date_to_feed_format( $date_stamp ) {
|
23 |
+
if ( $date_stamp ) {
|
24 |
+
// register the date
|
25 |
+
$feed_string = date( 'Y-m-d', $date_stamp );
|
26 |
+
|
27 |
+
// if set, add the time
|
28 |
+
if ( date( 'H', $date_stamp ) !== '00' || date( 'i', $date_stamp ) !== '00' || date( 's', $date_stamp ) !== '00' ) {
|
29 |
+
$feed_string .= 'T' . date( 'H:i:s', $date_stamp );
|
30 |
+
}
|
31 |
+
|
32 |
+
return $feed_string;
|
33 |
+
} else {
|
34 |
+
return '';
|
35 |
+
}
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* After a channel has been updated this function decreases the 'tvc_channels_to_update' option with one
|
40 |
+
*
|
41 |
+
* @since 1.4.1
|
42 |
+
*/
|
43 |
+
function tvc_decrease_update_ready_channels() {
|
44 |
+
$old = get_option( 'tvc_channels_to_update' );
|
45 |
+
|
46 |
+
if ( $old > 0 ) {
|
47 |
+
update_option( 'tvc_channels_to_update', $old - 1 );
|
48 |
+
} else {
|
49 |
+
update_option( 'tvc_channels_to_update', 0 );
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Checks the current database version and updates it if required
|
55 |
+
*
|
56 |
+
* @since 2.4.0
|
57 |
+
*/
|
58 |
+
function tvc_check_db_version() {
|
59 |
+
$db_management = new TVC_Database_Management();
|
60 |
+
$db_management->verify_db_version();
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Checks if a specific source key is a money related key or not
|
65 |
+
*
|
66 |
+
* @param string $key The source key to be checked
|
67 |
+
*
|
68 |
+
* @return boolean True if the source key is money related, false if not
|
69 |
+
* @since 1.1.0
|
70 |
+
*
|
71 |
+
*/
|
72 |
+
function tvc_meta_key_is_money( $key ) {
|
73 |
+
// money keys
|
74 |
+
$special_price_keys = array(
|
75 |
+
'_max_variation_price',
|
76 |
+
'_max_variation_regular_price',
|
77 |
+
'_max_variation_sale_price',
|
78 |
+
'_min_variation_price',
|
79 |
+
'_min_variation_regular_price',
|
80 |
+
'_min_variation_sale_price',
|
81 |
+
'_regular_price',
|
82 |
+
'_sale_price',
|
83 |
+
);
|
84 |
+
|
85 |
+
return in_array( $key, $special_price_keys ) ? true : false;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Takes a value and formats it to a money value using the WooCommerce thousands separator, decimal separator and number of decimals values
|
90 |
+
*
|
91 |
+
* @param string $money_va
|